@@ -121,8 +121,7 @@ module Database.PostgreSQL.Simple
121
121
import Data.ByteString.Builder
122
122
( Builder , byteString , char8 , intDec )
123
123
import Control.Applicative ((<$>) )
124
- import Control.Exception as E
125
- import Control.Monad (unless )
124
+ import Control.Monad (unless , void )
126
125
import Data.ByteString (ByteString )
127
126
import Data.Int (Int64 )
128
127
import Data.List (intersperse )
@@ -140,6 +139,8 @@ import Database.PostgreSQL.Simple.Transaction
140
139
import Database.PostgreSQL.Simple.TypeInfo
141
140
import qualified Database.PostgreSQL.LibPQ as PQ
142
141
import qualified Data.ByteString.Char8 as B
142
+ import Control.Monad.IO.Class
143
+ import Control.Monad.Catch as E
143
144
import Control.Monad.Trans.Reader
144
145
import Control.Monad.Trans.State.Strict
145
146
@@ -429,24 +430,24 @@ queryWith_ parser conn q@(Query que) = do
429
430
--
430
431
-- * 'SqlError': the postgresql backend returned an error, e.g.
431
432
-- 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 )
433
434
=> Connection
434
435
-> Query
435
436
-> params
436
437
-> a
437
- -> (a -> row -> IO a )
438
- -> IO a
438
+ -> (a -> row -> m a )
439
+ -> m a
439
440
fold = foldWithOptions defaultFoldOptions
440
441
441
442
-- | A version of 'fold' taking a parser as an argument
442
- foldWith :: ( ToRow params )
443
+ foldWith :: ( MonadIO m , MonadMask m , ToRow params )
443
444
=> RowParser row
444
445
-> Connection
445
446
-> Query
446
447
-> params
447
448
-> a
448
- -> (a -> row -> IO a )
449
- -> IO a
449
+ -> (a -> row -> m a )
450
+ -> m a
450
451
foldWith = foldWithOptionsAndParser defaultFoldOptions
451
452
452
453
-- | Number of rows to fetch at a time. 'Automatic' currently defaults
@@ -475,77 +476,80 @@ defaultFoldOptions = FoldOptions {
475
476
-- accordingly. If the connection is already in a transaction,
476
477
-- then the existing transaction is used and thus the 'transactionMode'
477
478
-- option is ignored.
478
- foldWithOptions :: ( FromRow row , ToRow params )
479
+ foldWithOptions :: ( MonadIO m , MonadMask m , FromRow row , ToRow params )
479
480
=> FoldOptions
480
481
-> Connection
481
482
-> Query
482
483
-> params
483
484
-> a
484
- -> (a -> row -> IO a )
485
- -> IO a
485
+ -> (a -> row -> m a )
486
+ -> m a
486
487
foldWithOptions opts = foldWithOptionsAndParser opts fromRow
487
488
488
489
-- | A version of 'foldWithOptions' taking a parser as an argument
489
- foldWithOptionsAndParser :: (ToRow params )
490
+ foldWithOptionsAndParser :: ( MonadIO m , MonadMask m , ToRow params )
490
491
=> FoldOptions
491
492
-> RowParser row
492
493
-> Connection
493
494
-> Query
494
495
-> params
495
496
-> a
496
- -> (a -> row -> IO a )
497
- -> IO a
497
+ -> (a -> row -> m a )
498
+ -> m a
498
499
foldWithOptionsAndParser opts parser conn template qs a f = do
499
- q <- formatQuery conn template qs
500
+ q <- liftIO $ formatQuery conn template qs
500
501
doFold opts parser conn template (Query q) a f
501
502
502
503
-- | 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
505
506
-> Query -- ^ Query.
506
507
-> 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
509
510
fold_ = foldWithOptions_ defaultFoldOptions
510
511
511
512
-- | A version of 'fold_' taking a parser as an argument
512
- foldWith_ :: RowParser r
513
+ foldWith_ :: ( MonadIO m , MonadMask m )
514
+ => RowParser r
513
515
-> Connection
514
516
-> Query
515
517
-> a
516
- -> (a -> r -> IO a )
517
- -> IO a
518
+ -> (a -> r -> m a )
519
+ -> m a
518
520
foldWith_ = foldWithOptionsAndParser_ defaultFoldOptions
519
521
520
- foldWithOptions_ :: (FromRow r ) =>
521
- FoldOptions
522
+ foldWithOptions_ :: ( MonadIO m , MonadMask m , FromRow r )
523
+ => FoldOptions
522
524
-> Connection
523
525
-> Query -- ^ Query.
524
526
-> 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
527
529
foldWithOptions_ opts conn query a f = doFold opts fromRow conn query query a f
528
530
529
531
-- | A version of 'foldWithOptions_' taking a parser as an argument
530
- foldWithOptionsAndParser_ :: FoldOptions
532
+ foldWithOptionsAndParser_ :: ( MonadIO m , MonadMask m )
533
+ => FoldOptions
531
534
-> RowParser r
532
535
-> Connection
533
536
-> Query -- ^ Query.
534
537
-> 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
537
540
foldWithOptionsAndParser_ opts parser conn query a f = doFold opts parser conn query query a f
538
541
539
- doFold :: FoldOptions
542
+ doFold :: ( MonadIO m , MonadMask m )
543
+ => FoldOptions
540
544
-> RowParser row
541
545
-> Connection
542
546
-> Query
543
547
-> Query
544
548
-> a
545
- -> (a -> row -> IO a )
546
- -> IO a
549
+ -> (a -> row -> m a )
550
+ -> m a
547
551
doFold FoldOptions {.. } parser conn _template q a0 f = do
548
- stat <- withConnection conn PQ. transactionStatus
552
+ stat <- liftIO $ withConnection conn PQ. transactionStatus
549
553
case stat of
550
554
PQ. TransIdle -> withTransactionMode transactionMode conn go
551
555
PQ. TransInTrans -> go
@@ -563,15 +567,15 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
563
567
-- Not sure what this means.
564
568
where
565
569
declare = do
566
- name <- newTempName conn
567
- _ <- execute_ conn $ mconcat
570
+ name <- liftIO $ newTempName conn
571
+ _ <- liftIO $ execute_ conn $ mconcat
568
572
[ " DECLARE " , name, " NO SCROLL CURSOR FOR " , q ]
569
573
return name
570
574
close name =
571
- (execute_ conn (" CLOSE " <> name) >> return ( ) ) `E.catch` \ ex ->
575
+ (void $ liftIO $ execute_ conn (" CLOSE " <> name)) `E.catch` \ ex ->
572
576
-- Don't throw exception if CLOSE failed because the transaction is
573
577
-- aborted. Otherwise, it will throw away the original error.
574
- unless (isFailedTransactionError ex) $ throwIO ex
578
+ unless (isFailedTransactionError ex) $ throwM ex
575
579
576
580
go = bracket declare close $ \ (Query name) ->
577
581
let q = toByteString (byteString " FETCH FORWARD "
@@ -580,20 +584,20 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
580
584
<> byteString name
581
585
)
582
586
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
585
589
case status of
586
590
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
589
593
if nrows > 0
590
594
then do
591
595
let inner a row = do
592
- x <- getRowWith parser row ncols conn result
596
+ x <- liftIO $ getRowWith parser row ncols conn result
593
597
f a x
594
598
foldM' inner a 0 (nrows - 1 ) >>= loop
595
599
else return a
596
- _ -> throwResultError " fold" result status
600
+ _ -> liftIO $ throwResultError " fold" result status
597
601
in loop a0
598
602
599
603
-- FIXME: choose the Automatic chunkSize more intelligently
@@ -607,44 +611,45 @@ doFold FoldOptions{..} parser conn _template q a0 f = do
607
611
Fixed n -> n
608
612
609
613
-- | 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
612
616
-> Query -- ^ Query template.
613
617
-> q -- ^ Query parameters.
614
- -> (r -> IO () ) -- ^ Result consumer.
615
- -> IO ()
618
+ -> (r -> m () ) -- ^ Result consumer.
619
+ -> m ()
616
620
forEach = forEachWith fromRow
617
621
{-# INLINE forEach #-}
618
622
619
623
-- | A version of 'forEach' taking a parser as an argument
620
- forEachWith :: ( ToRow q )
624
+ forEachWith :: ( MonadIO m , MonadMask m , ToRow q )
621
625
=> RowParser r
622
626
-> Connection
623
627
-> Query
624
628
-> q
625
- -> (r -> IO () )
626
- -> IO ()
629
+ -> (r -> m () )
630
+ -> m ()
627
631
forEachWith parser conn template qs = foldWith parser conn template qs () . const
628
632
{-# INLINE forEachWith #-}
629
633
630
634
-- | 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
633
637
-> Query -- ^ Query template.
634
- -> (r -> IO () ) -- ^ Result consumer.
635
- -> IO ()
638
+ -> (r -> m () ) -- ^ Result consumer.
639
+ -> m ()
636
640
forEach_ = forEachWith_ fromRow
637
641
{-# INLINE forEach_ #-}
638
642
639
- forEachWith_ :: RowParser r
643
+ forEachWith_ :: ( MonadIO m , MonadMask m )
644
+ => RowParser r
640
645
-> Connection
641
646
-> Query
642
- -> (r -> IO () )
643
- -> IO ()
647
+ -> (r -> m () )
648
+ -> m ()
644
649
forEachWith_ parser conn template = foldWith_ parser conn template () . const
645
650
{-# INLINE forEachWith_ #-}
646
651
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 ]
648
653
forM' lo hi m = loop hi []
649
654
where
650
655
loop ! n ! as
@@ -654,7 +659,7 @@ forM' lo hi m = loop hi []
654
659
loop (n- 1 ) (a: as)
655
660
{-# INLINE forM' #-}
656
661
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
658
663
foldM' f a lo hi = loop a lo
659
664
where
660
665
loop a ! n
@@ -669,18 +674,18 @@ finishQueryWith parser conn q result = do
669
674
status <- PQ. resultStatus result
670
675
case status of
671
676
PQ. EmptyQuery ->
672
- throwIO $ QueryError " query: Empty query" q
677
+ throwM $ QueryError " query: Empty query" q
673
678
PQ. CommandOk ->
674
- throwIO $ QueryError " query resulted in a command response" q
679
+ throwM $ QueryError " query resulted in a command response" q
675
680
PQ. TuplesOk -> do
676
681
nrows <- PQ. ntuples result
677
682
ncols <- PQ. nfields result
678
683
forM' 0 (nrows- 1 ) $ \ row ->
679
684
getRowWith parser row ncols conn result
680
685
PQ. CopyOut ->
681
- throwIO $ QueryError " query: COPY TO is not supported" q
686
+ throwM $ QueryError " query: COPY TO is not supported" q
682
687
PQ. CopyIn ->
683
- throwIO $ QueryError " query: COPY FROM is not supported" q
688
+ throwM $ QueryError " query: COPY FROM is not supported" q
684
689
PQ. BadResponse -> throwResultError " query" result status
685
690
PQ. NonfatalError -> throwResultError " query" result status
686
691
PQ. FatalError -> throwResultError " query" result status
@@ -698,16 +703,16 @@ getRowWith parser row ncols conn result = do
698
703
v <- PQ. getvalue result row c
699
704
return ( tinfo
700
705
, fmap ellipsis v )
701
- throw (ConversionFailed
706
+ throwM (ConversionFailed
702
707
(show (unCol ncols) ++ " values: " ++ show vals)
703
708
Nothing
704
709
" "
705
710
(show (unCol col) ++ " slots in target type" )
706
711
" mismatch between number of columns to \
707
712
\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
711
716
712
717
ellipsis :: ByteString -> ByteString
713
718
ellipsis bs
0 commit comments