@@ -121,8 +121,7 @@ module Database.PostgreSQL.Simple
121121import Data.ByteString.Builder
122122 ( Builder , byteString , char8 , intDec )
123123import Control.Applicative ((<$>) )
124- import Control.Exception as E
125- import Control.Monad (unless )
124+ import Control.Monad (unless , void )
126125import Data.ByteString (ByteString )
127126import Data.Int (Int64 )
128127import Data.List (intersperse )
@@ -140,6 +139,8 @@ import Database.PostgreSQL.Simple.Transaction
140139import Database.PostgreSQL.Simple.TypeInfo
141140import qualified Database.PostgreSQL.LibPQ as PQ
142141import qualified Data.ByteString.Char8 as B
142+ import Control.Monad.IO.Class
143+ import Control.Monad.Catch as E
143144import Control.Monad.Trans.Reader
144145import Control.Monad.Trans.State.Strict
145146
@@ -429,24 +430,24 @@ queryWith_ parser conn q@(Query que) = do
429430--
430431-- * 'SqlError': the postgresql backend returned an error, e.g.
431432-- a syntax or type error, or an incorrect table or column name.
432- fold :: ( FromRow row , ToRow params )
433+ fold :: ( MonadIO m , MonadMask m , FromRow row , ToRow params )
433434 => Connection
434435 -> Query
435436 -> params
436437 -> a
437- -> (a -> row -> IO a )
438- -> IO a
438+ -> (a -> row -> m a )
439+ -> m a
439440fold = foldWithOptions defaultFoldOptions
440441
441442-- | A version of 'fold' taking a parser as an argument
442- foldWith :: ( ToRow params )
443+ foldWith :: ( MonadIO m , MonadMask m , ToRow params )
443444 => RowParser row
444445 -> Connection
445446 -> Query
446447 -> params
447448 -> a
448- -> (a -> row -> IO a )
449- -> IO a
449+ -> (a -> row -> m a )
450+ -> m a
450451foldWith = foldWithOptionsAndParser defaultFoldOptions
451452
452453-- | Number of rows to fetch at a time. 'Automatic' currently defaults
@@ -475,77 +476,80 @@ defaultFoldOptions = FoldOptions {
475476-- accordingly. If the connection is already in a transaction,
476477-- then the existing transaction is used and thus the 'transactionMode'
477478-- option is ignored.
478- foldWithOptions :: ( FromRow row , ToRow params )
479+ foldWithOptions :: ( MonadIO m , MonadMask m , FromRow row , ToRow params )
479480 => FoldOptions
480481 -> Connection
481482 -> Query
482483 -> params
483484 -> a
484- -> (a -> row -> IO a )
485- -> IO a
485+ -> (a -> row -> m a )
486+ -> m a
486487foldWithOptions opts = foldWithOptionsAndParser opts fromRow
487488
488489-- | A version of 'foldWithOptions' taking a parser as an argument
489- foldWithOptionsAndParser :: (ToRow params )
490+ foldWithOptionsAndParser :: ( MonadIO m , MonadMask m , ToRow params )
490491 => FoldOptions
491492 -> RowParser row
492493 -> Connection
493494 -> Query
494495 -> params
495496 -> a
496- -> (a -> row -> IO a )
497- -> IO a
497+ -> (a -> row -> m a )
498+ -> m a
498499foldWithOptionsAndParser opts parser conn template qs a f = do
499- q <- formatQuery conn template qs
500+ q <- liftIO $ formatQuery conn template qs
500501 doFold opts parser conn template (Query q) a f
501502
502503-- | A version of 'fold' that does not perform query substitution.
503- fold_ :: (FromRow r ) =>
504- Connection
504+ fold_ :: ( MonadIO m , MonadMask m , FromRow r )
505+ => Connection
505506 -> Query -- ^ Query.
506507 -> a -- ^ Initial state for result consumer.
507- -> (a -> r -> IO a ) -- ^ Result consumer.
508- -> IO a
508+ -> (a -> r -> m a ) -- ^ Result consumer.
509+ -> m a
509510fold_ = foldWithOptions_ defaultFoldOptions
510511
511512-- | A version of 'fold_' taking a parser as an argument
512- foldWith_ :: RowParser r
513+ foldWith_ :: ( MonadIO m , MonadMask m )
514+ => RowParser r
513515 -> Connection
514516 -> Query
515517 -> a
516- -> (a -> r -> IO a )
517- -> IO a
518+ -> (a -> r -> m a )
519+ -> m a
518520foldWith_ = foldWithOptionsAndParser_ defaultFoldOptions
519521
520- foldWithOptions_ :: (FromRow r ) =>
521- FoldOptions
522+ foldWithOptions_ :: ( MonadIO m , MonadMask m , FromRow r )
523+ => FoldOptions
522524 -> Connection
523525 -> Query -- ^ Query.
524526 -> a -- ^ Initial state for result consumer.
525- -> (a -> r -> IO a ) -- ^ Result consumer.
526- -> IO a
527+ -> (a -> r -> m a ) -- ^ Result consumer.
528+ -> m a
527529foldWithOptions_ opts conn query a f = doFold opts fromRow conn query query a f
528530
529531-- | A version of 'foldWithOptions_' taking a parser as an argument
530- foldWithOptionsAndParser_ :: FoldOptions
532+ foldWithOptionsAndParser_ :: ( MonadIO m , MonadMask m )
533+ => FoldOptions
531534 -> RowParser r
532535 -> Connection
533536 -> Query -- ^ Query.
534537 -> a -- ^ Initial state for result consumer.
535- -> (a -> r -> IO a ) -- ^ Result consumer.
536- -> IO a
538+ -> (a -> r -> m a ) -- ^ Result consumer.
539+ -> m a
537540foldWithOptionsAndParser_ opts parser conn query a f = doFold opts parser conn query query a f
538541
539- doFold :: FoldOptions
542+ doFold :: ( MonadIO m , MonadMask m )
543+ => FoldOptions
540544 -> RowParser row
541545 -> Connection
542546 -> Query
543547 -> Query
544548 -> a
545- -> (a -> row -> IO a )
546- -> IO a
549+ -> (a -> row -> m a )
550+ -> m a
547551doFold FoldOptions {.. } parser conn _template q a0 f = do
548- stat <- withConnection conn PQ. transactionStatus
552+ stat <- liftIO $ withConnection conn PQ. transactionStatus
549553 case stat of
550554 PQ. TransIdle -> withTransactionMode transactionMode conn go
551555 PQ. TransInTrans -> go
@@ -563,15 +567,15 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
563567 -- Not sure what this means.
564568 where
565569 declare = do
566- name <- newTempName conn
567- _ <- execute_ conn $ mconcat
570+ name <- liftIO $ newTempName conn
571+ _ <- liftIO $ execute_ conn $ mconcat
568572 [ " DECLARE " , name, " NO SCROLL CURSOR FOR " , q ]
569573 return name
570574 close name =
571- (execute_ conn (" CLOSE " <> name) >> return ( ) ) `E.catch` \ ex ->
575+ (void $ liftIO $ execute_ conn (" CLOSE " <> name)) `E.catch` \ ex ->
572576 -- Don't throw exception if CLOSE failed because the transaction is
573577 -- aborted. Otherwise, it will throw away the original error.
574- unless (isFailedTransactionError ex) $ throwIO ex
578+ unless (isFailedTransactionError ex) $ throwM ex
575579
576580 go = bracket declare close $ \ (Query name) ->
577581 let q = toByteString (byteString " FETCH FORWARD "
@@ -580,20 +584,20 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
580584 <> byteString name
581585 )
582586 loop a = do
583- result <- exec conn q
584- status <- PQ. resultStatus result
587+ result <- liftIO $ exec conn q
588+ status <- liftIO $ PQ. resultStatus result
585589 case status of
586590 PQ. TuplesOk -> do
587- nrows <- PQ. ntuples result
588- ncols <- PQ. nfields result
591+ nrows <- liftIO $ PQ. ntuples result
592+ ncols <- liftIO $ PQ. nfields result
589593 if nrows > 0
590594 then do
591595 let inner a row = do
592- x <- getRowWith parser row ncols conn result
596+ x <- liftIO $ getRowWith parser row ncols conn result
593597 f a x
594598 foldM' inner a 0 (nrows - 1 ) >>= loop
595599 else return a
596- _ -> throwResultError " fold" result status
600+ _ -> liftIO $ throwResultError " fold" result status
597601 in loop a0
598602
599603-- FIXME: choose the Automatic chunkSize more intelligently
@@ -607,44 +611,45 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
607611 Fixed n -> n
608612
609613-- | A version of 'fold' that does not transform a state value.
610- forEach :: (ToRow q , FromRow r ) =>
611- Connection
614+ forEach :: ( MonadIO m , MonadMask m , ToRow q , FromRow r )
615+ => Connection
612616 -> Query -- ^ Query template.
613617 -> q -- ^ Query parameters.
614- -> (r -> IO () ) -- ^ Result consumer.
615- -> IO ()
618+ -> (r -> m () ) -- ^ Result consumer.
619+ -> m ()
616620forEach = forEachWith fromRow
617621{-# INLINE forEach #-}
618622
619623-- | A version of 'forEach' taking a parser as an argument
620- forEachWith :: ( ToRow q )
624+ forEachWith :: ( MonadIO m , MonadMask m , ToRow q )
621625 => RowParser r
622626 -> Connection
623627 -> Query
624628 -> q
625- -> (r -> IO () )
626- -> IO ()
629+ -> (r -> m () )
630+ -> m ()
627631forEachWith parser conn template qs = foldWith parser conn template qs () . const
628632{-# INLINE forEachWith #-}
629633
630634-- | A version of 'forEach' that does not perform query substitution.
631- forEach_ :: (FromRow r ) =>
632- Connection
635+ forEach_ :: ( MonadIO m , MonadMask m , FromRow r )
636+ => Connection
633637 -> Query -- ^ Query template.
634- -> (r -> IO () ) -- ^ Result consumer.
635- -> IO ()
638+ -> (r -> m () ) -- ^ Result consumer.
639+ -> m ()
636640forEach_ = forEachWith_ fromRow
637641{-# INLINE forEach_ #-}
638642
639- forEachWith_ :: RowParser r
643+ forEachWith_ :: ( MonadIO m , MonadMask m )
644+ => RowParser r
640645 -> Connection
641646 -> Query
642- -> (r -> IO () )
643- -> IO ()
647+ -> (r -> m () )
648+ -> m ()
644649forEachWith_ parser conn template = foldWith_ parser conn template () . const
645650{-# INLINE forEachWith_ #-}
646651
647- forM' :: (Ord n , Num n ) => n -> n -> (n -> IO a ) -> IO [a ]
652+ forM' :: (Monad m , Ord n , Num n ) => n -> n -> (n -> m a ) -> m [a ]
648653forM' lo hi m = loop hi []
649654 where
650655 loop ! n ! as
@@ -654,7 +659,7 @@ forM' lo hi m = loop hi []
654659 loop (n- 1 ) (a: as)
655660{-# INLINE forM' #-}
656661
657- foldM' :: (Ord n , Num n ) => (a -> n -> IO a ) -> a -> n -> n -> IO a
662+ foldM' :: (Monad m , Ord n , Num n ) => (a -> n -> m a ) -> a -> n -> n -> m a
658663foldM' f a lo hi = loop a lo
659664 where
660665 loop a ! n
@@ -669,18 +674,18 @@ finishQueryWith parser conn q result = do
669674 status <- PQ. resultStatus result
670675 case status of
671676 PQ. EmptyQuery ->
672- throwIO $ QueryError " query: Empty query" q
677+ throwM $ QueryError " query: Empty query" q
673678 PQ. CommandOk ->
674- throwIO $ QueryError " query resulted in a command response" q
679+ throwM $ QueryError " query resulted in a command response" q
675680 PQ. TuplesOk -> do
676681 nrows <- PQ. ntuples result
677682 ncols <- PQ. nfields result
678683 forM' 0 (nrows- 1 ) $ \ row ->
679684 getRowWith parser row ncols conn result
680685 PQ. CopyOut ->
681- throwIO $ QueryError " query: COPY TO is not supported" q
686+ throwM $ QueryError " query: COPY TO is not supported" q
682687 PQ. CopyIn ->
683- throwIO $ QueryError " query: COPY FROM is not supported" q
688+ throwM $ QueryError " query: COPY FROM is not supported" q
684689 PQ. BadResponse -> throwResultError " query" result status
685690 PQ. NonfatalError -> throwResultError " query" result status
686691 PQ. FatalError -> throwResultError " query" result status
@@ -698,16 +703,16 @@ getRowWith parser row ncols conn result = do
698703 v <- PQ. getvalue result row c
699704 return ( tinfo
700705 , fmap ellipsis v )
701- throw (ConversionFailed
706+ throwM (ConversionFailed
702707 (show (unCol ncols) ++ " values: " ++ show vals)
703708 Nothing
704709 " "
705710 (show (unCol col) ++ " slots in target type" )
706711 " mismatch between number of columns to \
707712 \convert and number in target type" )
708- Errors [] -> throwIO $ ConversionFailed " " Nothing " " " " " unknown error"
709- Errors [x] -> throwIO x
710- Errors xs -> throwIO $ ManyErrors xs
713+ Errors [] -> throwM $ ConversionFailed " " Nothing " " " " " unknown error"
714+ Errors [x] -> throwM x
715+ Errors xs -> throwM $ ManyErrors xs
711716
712717ellipsis :: ByteString -> ByteString
713718ellipsis bs
0 commit comments