Add errors and optional fields

This commit is contained in:
2023-09-04 23:46:51 +02:00
parent 8c8740e4b8
commit 7a14714cf6
7 changed files with 165 additions and 55 deletions
+14
View File
@@ -0,0 +1,14 @@
module Database.PostgreSQL.Opium.Error (Error (..)) where
import Data.Text (Text)
import Database.PostgreSQL.LibPQ (ExecStatus, Row)
import Database.PostgreSQL.Opium.FromField (FieldError)
data Error
= ErrorDecode Row Text FieldError
| ErrorNoResult
| ErrorInvalidResult ExecStatus Text
| ErrorMissingColumn Text
| ErrorUnexpectedNull Row Text
deriving (Eq, Show)
+25 -16
View File
@@ -1,13 +1,17 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Database.PostgreSQL.Opium.FromField (FromField (..)) where
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)
@@ -18,23 +22,30 @@ import qualified Database.PostgreSQL.Opium.Oid as Oid
(\/) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
p \/ q = \x -> p x || q x
eitherToMaybe :: Either b a -> Maybe a
eitherToMaybe = \case
Left _ -> Nothing
Right x -> Just 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
-> Maybe a
fromParser validOid parser oid value
| validOid oid = eitherToMaybe $ parseOnly parser value
| otherwise = Nothing
-> 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 -> Maybe a
fromField :: Oid -> Text -> Either FieldError a
instance FromField Int where
fromField = fromParser
@@ -42,11 +53,9 @@ instance FromField Int where
(signed decimal)
instance FromField Text where
fromField oid text =
if Oid.text oid || Oid.character oid || Oid.characterVarying oid then
Just text
else
Nothing
fromField = fromParser
(Oid.text \/ Oid.character \/ Oid.characterVarying)
takeText
instance FromField String where
fromField oid text = Text.unpack <$> fromField oid text