62 lines
1.4 KiB
Haskell
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
|