@@ -30,6 +30,7 @@ import Data.Either()
3030import Database.PostgreSQL.Simple.Internal
3131import Database.PostgreSQL.Simple.Result (ResultError(..), Result(..))
3232import Database.PostgreSQL.Simple.Types (Only(..))
33+import qualified Database.PostgreSQL.LibPQ as LibPQ (Result)
3334
3435-- | A collection type that can be converted from a list of strings.
3536--
@@ -42,41 +43,53 @@ import Database.PostgreSQL.Simple.Types (Only(..))
4243--
4344-- @
4445-- instance ('Result' a, 'Result' b) => 'QueryResults' (a,b) where
45−-- 'convertResults' [fa,fb] [va,vb] = (a,b)
46−-- where !a = 'convert' fa va
47−-- !b = 'convert' fb vb
46+-- 'convertResults' [fa,fb] [va,vb] = do
47+-- !a <- 'convert' fa va
48+-- !b <- 'convert' fb vb
49+-- 'return' (a,b)
4850-- 'convertResults' fs vs = 'convertError' fs vs 2
4951-- @
5052--
5153-- Notice that this instance evaluates each element to WHNF before
52−-- constructing the pair. By doing this, we guarantee two important
53−-- properties:
54+-- constructing the pair. This property is important enough that its
55+-- a rule all 'QueryResult' instances should follow:
5456--
55−-- * Keep resource usage under control by preventing the construction
56−-- of potentially long-lived thunks.
57+-- * Evaluate every 'Result' value to WHNF before constructing
58+-- the result
5759--
58−-- * Ensure that any 'ResultError' that might arise is thrown
59−-- immediately, rather than some place later in application code
60−-- that cannot handle it.
60+-- Doing so keeps resource usage under local control by preventing the
61+-- construction of potentially long-lived thunks that are forced
62+-- (or not) by the consumer.
6163--
62−-- You can also declare Haskell types of your own to be instances of
63−-- 'QueryResults'.
64+-- This is important to postgresql-simple-0.0.4 because a wayward thunk
65+-- causes the entire LibPQ.'LibPQ.Result' to be retained. This could lead
66+-- to a memory leak, depending on how the thunk is consumed.
67+--
68+-- Note that instances can be defined outside of postgresql-simple,
69+-- which is often useful. For example, here is an attempt at an
70+-- instance for a user-defined pair:
6471--
6572-- @
66−--data User { firstName :: String, lastName :: String }
73+-- data User = User { firstName :: String, lastName :: String }
6774--
68−--instance 'QueryResults' User where
69−-- 'convertResults' [fa,fb] [va,vb] = User a b
70−-- where !a = 'convert' fa va
71−-- !b = 'convert' fb vb
72−-- 'convertResults' fs vs = 'convertError' fs vs
75+-- instance 'QueryResults' User where
76+-- 'convertResults' [fa,qfb] [va,vb] = User \<$\> a \<*\> b
77+-- where !a = 'convert' fa va
78+-- !b = 'convert' fb vb
79+-- 'convertResults' fs vs = 'convertError' fs vs 2
7380-- @
81+--
82+-- In this example, the bang patterns are not used correctly. They force
83+-- the data constructors of the 'Either' type, and are not forcing the
84+-- 'Result' values we need to force. This gives the consumer of the
85+-- 'QueryResult' the ability to cause the memory leak, which is an
86+-- undesirable state of affairs.
7487
7588class QueryResults a where
7689 convertResults :: [Field] -> [Maybe ByteString] -> Either SomeException a
7790 -- ^ Convert values from a row into a Haskell collection.
7891 --
79− -- This function will throw a 'ResultError' if conversion of the
92+ -- This function will return a 'ResultError' if conversion of the
8093 -- collection fails.
8194
8295instance (Result a) => QueryResults (Only a) where