git.iko.soy/typeable/postgresql-simple
on master help sign in
Merge pull request #147 from tstat/streaming
13e8ea6Leon P Smith
src/Database/PostgreSQL/Simple.hs+84−14
@@ -93,6 +93,14 @@ module Database.PostgreSQL.Simple
93 , forEach
93 , forEach
94 , forEach_
94 , forEach_
95 , returning
95 , returning
96+ -- ** Queries that stream results taking a parser as an argument
97+ , foldWith
98+ , foldWithOptionsAndParser
99+ , foldWith_
100+ , foldWithOptionsAndParser_
101+ , forEachWith
102+ , forEachWith_
103+ , returningWith
96 -- * Statements that do not return results
104 -- * Statements that do not return results
97 , execute
105 , execute
98 , execute_
106 , execute_
@@ -349,10 +357,13 @@ executeMany conn q qs = do
349--
357--
350-- Throws 'FormatError' if the query could not be formatted correctly.
358-- Throws 'FormatError' if the query could not be formatted correctly.
351returning :: (ToRow q, FromRow r) => Connection -> Query -> [q] -> IO [r]
359returning :: (ToRow q, FromRow r) => Connection -> Query -> [q] -> IO [r]
360+returning = returningWith fromRow
361+
362+returningWith :: (ToRow q) => RowParser r -> Connection -> Query -> [q] -> IO [r]
352−returning _ _ [] = return []
363+returningWith _ _ _ [] = return []
353−returning conn q qs = do
364+returningWith parser conn q qs = do
354 result <- exec conn =<< formatMany conn q qs
365 result <- exec conn =<< formatMany conn q qs
355− finishQuery conn q result
366+ finishQueryWith parser conn q result
356
367
357-- | Perform a @SELECT@ or other SQL query that is expected to return
368-- | Perform a @SELECT@ or other SQL query that is expected to return
358-- results. All results are retrieved and converted before this
369-- results. All results are retrieved and converted before this
@@ -427,6 +438,17 @@ fold :: ( FromRow row, ToRow params )
427 -> IO a
438 -> IO a
428fold = foldWithOptions defaultFoldOptions
439fold = foldWithOptions defaultFoldOptions
429
440
441+-- | A version of 'fold' taking a parser as an argument
442+foldWith :: ( ToRow params )
443+ => RowParser row
444+ -> Connection
445+ -> Query
446+ -> params
447+ -> a
448+ -> (a -> row -> IO a)
449+ -> IO a
450+foldWith = foldWithOptionsAndParser defaultFoldOptions
451+
430-- | Number of rows to fetch at a time. 'Automatic' currently defaults
452-- | Number of rows to fetch at a time. 'Automatic' currently defaults
431-- to 256 rows, although it might be nice to make this more intelligent
453-- to 256 rows, although it might be nice to make this more intelligent
432-- based on e.g. the average size of the rows.
454-- based on e.g. the average size of the rows.
@@ -461,9 +483,21 @@ foldWithOptions :: ( FromRow row, ToRow params )
461 -> a
483 -> a
462 -> (a -> row -> IO a)
484 -> (a -> row -> IO a)
463 -> IO a
485 -> IO a
464−foldWithOptions opts conn template qs a f = do
486+foldWithOptions opts = foldWithOptionsAndParser opts fromRow
487+
488+-- | A version of 'foldWithOptions' taking a parser as an argument
489+foldWithOptionsAndParser :: (ToRow params)
490+ => FoldOptions
491+ -> RowParser row
492+ -> Connection
493+ -> Query
494+ -> params
495+ -> a
496+ -> (a -> row -> IO a)
497+ -> IO a
498+foldWithOptionsAndParser opts parser conn template qs a f = do
465 q <- formatQuery conn template qs
499 q <- formatQuery conn template qs
466− doFold opts conn template (Query q) a f
500+ doFold opts parser conn template (Query q) a f
467
501
468-- | A version of 'fold' that does not perform query substitution.
502-- | A version of 'fold' that does not perform query substitution.
469fold_ :: (FromRow r) =>
503fold_ :: (FromRow r) =>
@@ -474,6 +508,14 @@ fold_ :: (FromRow r) =>
474 -> IO a
508 -> IO a
475fold_ = foldWithOptions_ defaultFoldOptions
509fold_ = foldWithOptions_ defaultFoldOptions
476
510
511+-- | A version of 'foldWith' taking a parser as an argument
512+foldWith_ :: RowParser r
513+ -> Connection
514+ -> Query
515+ -> a
516+ -> (a -> r -> IO a)
517+ -> IO a
518+foldWith_ = foldWithOptionsAndParser_ defaultFoldOptions
477
519
478foldWithOptions_ :: (FromRow r) =>
520foldWithOptions_ :: (FromRow r) =>
479 FoldOptions
521 FoldOptions
@@ -482,18 +524,27 @@ foldWithOptions_ :: (FromRow r) =>
482 -> a -- ^ Initial state for result consumer.
524 -> a -- ^ Initial state for result consumer.
483 -> (a -> r -> IO a) -- ^ Result consumer.
525 -> (a -> r -> IO a) -- ^ Result consumer.
484 -> IO a
526 -> IO a
485−foldWithOptions_ opts conn query a f = doFold opts conn query query a f
527+foldWithOptions_ opts conn query a f = doFold opts fromRow conn query query a f
486−
528+
487−
529+-- | A version of 'foldWithOptions_' taking a parser as an argument
488−doFold :: ( FromRow row )
530+foldWithOptionsAndParser_ :: FoldOptions
489− => FoldOptions
531+ -> RowParser r
532+ -> Connection
533+ -> Query -- ^ Query.
534+ -> a -- ^ Initial state for result consumer.
535+ -> (a -> r -> IO a) -- ^ Result consumer.
536+ -> IO a
537+foldWithOptionsAndParser_ opts parser conn query a f = doFold opts parser conn query query a f
538+
539+doFold :: FoldOptions
540+ -> RowParser row
490 -> Connection
541 -> Connection
491 -> Query
542 -> Query
492 -> Query
543 -> Query
493 -> a
544 -> a
494 -> (a -> row -> IO a)
545 -> (a -> row -> IO a)
495 -> IO a
546 -> IO a
496−doFold FoldOptions{..} conn _template q a0 f = do
547+doFold FoldOptions{..} parser conn _template q a0 f = do
497 stat <- withConnection conn PQ.transactionStatus
548 stat <- withConnection conn PQ.transactionStatus
498 case stat of
549 case stat of
499 PQ.TransIdle -> withTransactionMode transactionMode conn go
550 PQ.TransIdle -> withTransactionMode transactionMode conn go
@@ -516,7 +567,7 @@ doFold FoldOptions{..} conn _template q a0 f = do
516 _ <- execute_ conn $ mconcat
567 _ <- execute_ conn $ mconcat
517 [ "DECLARE ", name, " NO SCROLL CURSOR FOR ", q ]
568 [ "DECLARE ", name, " NO SCROLL CURSOR FOR ", q ]
518 return name
569 return name
519− fetch (Query name) = query_ conn $
570+ fetch (Query name) = queryWith_ parser conn $
520 Query (toByteString (byteString "FETCH FORWARD "
571 Query (toByteString (byteString "FETCH FORWARD "
521 <> intDec chunkSize
572 <> intDec chunkSize
522 <> byteString " FROM "
573 <> byteString " FROM "
@@ -551,18 +602,37 @@ forEach :: (ToRow q, FromRow r) =>
551 -> q -- ^ Query parameters.
602 -> q -- ^ Query parameters.
552 -> (r -> IO ()) -- ^ Result consumer.
603 -> (r -> IO ()) -- ^ Result consumer.
553 -> IO ()
604 -> IO ()
554−forEach conn template qs = fold conn template qs () . const
605+forEach = forEachWith fromRow
555{-# INLINE forEach #-}
606{-# INLINE forEach #-}
556
607
608+-- | A version of 'forEach' taking a parser as an argument
609+forEachWith :: ( ToRow q )
610+ => RowParser r
611+ -> Connection
612+ -> Query
613+ -> q
614+ -> (r -> IO ())
615+ -> IO ()
616+forEachWith parser conn template qs = foldWith parser conn template qs () . const
617+{-# INLINE forEachWith #-}
618+
557-- | A version of 'forEach' that does not perform query substitution.
619-- | A version of 'forEach' that does not perform query substitution.
558forEach_ :: (FromRow r) =>
620forEach_ :: (FromRow r) =>
559 Connection
621 Connection
560 -> Query -- ^ Query template.
622 -> Query -- ^ Query template.
561 -> (r -> IO ()) -- ^ Result consumer.
623 -> (r -> IO ()) -- ^ Result consumer.
562 -> IO ()
624 -> IO ()
563−forEach_ conn template = fold_ conn template () . const
625+forEach_ = forEachWith_ fromRow
564{-# INLINE forEach_ #-}
626{-# INLINE forEach_ #-}
565
627
628+forEachWith_ :: RowParser r
629+ -> Connection
630+ -> Query
631+ -> (r -> IO ())
632+ -> IO ()
633+forEachWith_ parser conn template = foldWith_ parser conn template () . const
634+{-# INLINE forEachWith_ #-}
635+
566forM' :: (Ord n, Num n) => n -> n -> (n -> IO a) -> IO [a]
636forM' :: (Ord n, Num n) => n -> n -> (n -> IO a) -> IO [a]
567forM' lo hi m = loop hi []
637forM' lo hi m = loop hi []
568 where
638 where
src/Database/PostgreSQL/Simple/LargeObjects.hs+1−1
@@ -14,7 +14,7 @@
14-- database transaction, so if you are interested in using anything beyond
14-- database transaction, so if you are interested in using anything beyond
15-- 'loCreat', 'loCreate', and 'loUnlink', you will need to run the entire
15-- 'loCreat', 'loCreate', and 'loUnlink', you will need to run the entire
16-- sequence of functions in a transaction. As 'loImport' and 'loExport'
16-- sequence of functions in a transaction. As 'loImport' and 'loExport'
17−-- are simply C functions that call 'loCreat', 'loOpen', 'loRead', and
17+-- are simply C functions that call 'loCreat', 'loOpen', 'loRead', and
18-- 'loWrite', and do not perform any transaction handling themselves,
18-- 'loWrite', and do not perform any transaction handling themselves,
19-- they also need to be wrapped in an explicit transaction.
19-- they also need to be wrapped in an explicit transaction.
20--
20--