Portability | portable |
---|---|
Stability | experimental |
Maintainer | Leon P Smith <leon@melding-monads.com> |
Safe Haskell | Safe-Infered |
The QueryResults
typeclass, for converting a row of results
returned by a SQL query into a more useful Haskell representation.
Predefined instances are provided for tuples containing up to ten elements.
- class QueryResults a where
- convertResults :: [Field] -> [Maybe ByteString] -> Either SomeException a
- convertError :: [Field] -> [Maybe ByteString] -> Int -> Either SomeException a
Documentation
class QueryResults a whereSource
A collection type that can be converted from a list of strings.
Instances should use the convert
method of the Result
class
to perform conversion of each element of the collection.
This example instance demonstrates how to convert a two-column row
into a Haskell pair. Each field in the metadata is paired up with
each value from the row, and the two are passed to convert
.
instance (Result
a,Result
b) =>QueryResults
(a,b) whereconvertResults
[fa,fb] [va,vb] = do !a <-convert
fa va !b <-convert
fb vbreturn
(a,b)convertResults
fs vs =convertError
fs vs 2
Notice that this instance evaluates each element to WHNF before
constructing the pair. This property is important enough that its
a rule all QueryResult
instances should follow:
- Evaluate every
Result
value to WHNF before constructing the result
Doing so keeps resource usage under local control by preventing the construction of potentially long-lived thunks that are forced (or not) by the consumer.
This is important to postgresql-simple-0.0.4 because a wayward thunk
causes the entire LibPQ.Result
to be retained. This could lead
to a memory leak, depending on how the thunk is consumed.
Note that instances can be defined outside of postgresql-simple, which is often useful. For example, here is an attempt at an instance for a user-defined pair:
data User = User { firstName :: String, lastName :: String } instanceQueryResults
User whereconvertResults
[fa,qfb] [va,vb] = User <$> a <*> b where !a =convert
fa va !b =convert
fb vbconvertResults
fs vs =convertError
fs vs 2
In this example, the bang patterns are not used correctly. They force
the data constructors of the Either
type, and are not forcing the
Result
values we need to force. This gives the consumer of the
QueryResult
the ability to cause the memory leak, which is an
undesirable state of affairs.
convertResults :: [Field] -> [Maybe ByteString] -> Either SomeException aSource
Convert values from a row into a Haskell collection.
This function will return a ResultError
if conversion of the
collection fails.
Result a => QueryResults [a] | |
Result a => QueryResults (Only a) | |
(Result a, Result b) => QueryResults (a, b) | |
(Result a, Result b, Result c) => QueryResults (a, b, c) | |
(Result a, Result b, Result c, Result d) => QueryResults (a, b, c, d) | |
(Result a, Result b, Result c, Result d, Result e) => QueryResults (a, b, c, d, e) | |
(Result a, Result b, Result c, Result d, Result e, Result f) => QueryResults (a, b, c, d, e, f) | |
(Result a, Result b, Result c, Result d, Result e, Result f, Result g) => QueryResults (a, b, c, d, e, f, g) | |
(Result a, Result b, Result c, Result d, Result e, Result f, Result g, Result h) => QueryResults (a, b, c, d, e, f, g, h) | |
(Result a, Result b, Result c, Result d, Result e, Result f, Result g, Result h, Result i) => QueryResults (a, b, c, d, e, f, g, h, i) | |
(Result a, Result b, Result c, Result d, Result e, Result f, Result g, Result h, Result i, Result j) => QueryResults (a, b, c, d, e, f, g, h, i, j) |
:: [Field] | Descriptors of fields to be converted. |
-> [Maybe ByteString] | Contents of the row to be converted. |
-> Int | Number of columns expected for conversion. For instance, if converting to a 3-tuple, the number to provide here would be 3. |
-> Either SomeException a |
Throw a ConversionFailed
exception, indicating a mismatch
between the number of columns in the Field
and row, and the
number in the collection to be converted to.