postgresql-simple-0.0.4: Mid-Level PostgreSQL client library

Portabilityportable
Stabilityexperimental
MaintainerLeon P Smith <leon@melding-monads.com>
Safe HaskellSafe-Infered

Database.PostgreSQL.Simple.QueryResults

Description

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.

Synopsis

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) where
     convertResults [fa,fb] [va,vb] = do
               !a <- convert fa va
               !b <- convert fb vb
               return (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 }

instance QueryResults User where
     convertResults [fa,qfb] [va,vb] = User <$> a <*> b
        where  !a =  convert fa va
               !b =  convert fb vb
     convertResults 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.

Methods

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.

Instances

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) 

convertErrorSource

Arguments

:: [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.