@@ -23,12 +23,51 @@
23-- since a 'Double' might lose precision if representing a 64-bit @BigInt@,
23-- since a 'Double' might lose precision if representing a 64-bit @BigInt@,
24-- the two are /not/ considered compatible.
24-- the two are /not/ considered compatible.
26+-- Because 'FromField' is a typeclass, one may provide conversions to
27+-- additional Haskell types without modifying postgresql-simple. This is
28+-- particularly useful for supporting PostgreSQL types that postgresql-simple
29+-- does not support out-of-box. Here's an example of what such an instance
30+-- might look like for a UUID type that implements the @Read@ class:
33+-- import Data.UUID ( UUID )
34+-- import Database.PostgreSQL.Simple.BuiltinTypes
35+-- ( BuiltinType(UUID), builtin2oid )
36+-- import qualified Data.ByteString as B
38+-- instance FromField UUID where
39+-- fromField f mdata =
40+-- if typeOid f /= builtin2oid UUID
41+-- then returnError Incompatible f ""
42+-- else case B.unpack `fmap` mdata of
43+-- Nothing -> returnError UnexpectedNull f ""
45+-- case [ x | (x,t) <- reads data, ("","") <- lex t ] of
47+-- _ -> returnError ConversionError f data
50+-- Note that because PostgreSQL's @uuid@ type is built into postgres and is
51+-- not provided by an extension, the 'typeOid' of @uuid@ does not change and
52+-- thus we can examine it directly. Here, we simply pull the type oid out
53+-- of the static table provided by postgresql-simple.
55+-- On the other hand if the type is provided by an extension, such as
56+-- @PostGIS@ or @hstore@, then the 'typeOid' is not stable and can vary from
57+-- database to database. In this case it is recommended that FromField
58+-- instances use 'typename' instead.
26------------------------------------------------------------------------------
60------------------------------------------------------------------------------
28module Database.PostgreSQL.Simple.FromField
62module Database.PostgreSQL.Simple.FromField
30 FromField(..)
64 FromField(..)
31 , FieldParser
65 , FieldParser
32 , ResultError(..)
71 , ResultError(..)
33 , returnError
72 , returnError
@@ -294,7 +333,7 @@ instance FromField LocalTimestamp where
294instance FromField Date where
333instance FromField Date where
295 fromField = ff Date parseDate
334 fromField = ff Date parseDate
297−ff :: Typeable a
336+ff :: Typeable a
298 => BuiltinType -> (B8.ByteString -> Either String a)
337 => BuiltinType -> (B8.ByteString -> Either String a)
299 -> Field -> Maybe B8.ByteString -> Conversion a
338 -> Field -> Maybe B8.ByteString -> Conversion a
300ff pgType parse f mstr =
339ff pgType parse f mstr =