62 lines
1.4 KiB
Haskell

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Database.PostgreSQL.Opium.FromField
( FieldError (..)
, FromField (..)
) where
import Data.Attoparsec.Text
( Parser
, decimal
, parseOnly
, signed
, takeText
)
import Data.Text (Text)
import Database.PostgreSQL.LibPQ (Oid)
import qualified Data.Text as Text
import qualified Database.PostgreSQL.Opium.Oid as Oid
(\/) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
p \/ q = \x -> p x || q x
data FieldError
= FieldErrorUnexpectedNull
| FieldErrorInvalidOid Oid
| FieldErrorInvalidField Oid Text String
deriving (Eq, Show)
mapLeft :: (b -> c) -> Either b a -> Either c a
mapLeft f (Left l) = Left $ f l
mapLeft _ (Right r) = Right r
fromParser
:: (Oid -> Bool)
-> Parser a
-> Oid
-> Text
-> Either FieldError a
fromParser validOid parser oid field
| validOid oid =
mapLeft (FieldErrorInvalidField oid field) $ parseOnly parser field
| otherwise =
Left $ FieldErrorInvalidOid oid
class FromField a where
fromField :: Oid -> Text -> Either FieldError a
instance FromField Int where
fromField = fromParser
(Oid.smallint \/ Oid.integer \/ Oid.bigint)
(signed decimal)
instance FromField Text where
fromField = fromParser
(Oid.text \/ Oid.character \/ Oid.characterVarying)
takeText
instance FromField String where
fromField oid text = Text.unpack <$> fromField oid text