From 60f7f1c0913c35635ebbab4649a15de2e8310e81 Mon Sep 17 00:00:00 2001 From: Paul Brinkmeier Date: Tue, 5 Sep 2023 17:23:25 +0200 Subject: [PATCH] Implement FromField Bool --- README.md | 6 ++++-- lib/Database/PostgreSQL/Opium/FromField.hs | 12 ++++++++++++ lib/Database/PostgreSQL/Opium/Oid.hs | 4 ++++ .../PostgreSQL/Opium/FromFieldSpec.hs | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bd65508..b853ac5 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ - [x] Implement `String` and `Text` decoding - [x] Implement `Int` decoding -- [ ] Implement error reporting i.e. use `Either OpiumError` instead of `Maybe` -- [ ] Implement `Float` and `Double` decoding +- [x] Implement error reporting i.e. use `Either OpiumError` instead of `Maybe` +- [x] Implement `Float` and `Double` decoding - [ ] Implement `UTCTime` and zoned time decoding +- [ ] Implement `ByteString` decoding (`bytea`) + - Can we make let the fromField instance choose whether it wants binary or text? diff --git a/lib/Database/PostgreSQL/Opium/FromField.hs b/lib/Database/PostgreSQL/Opium/FromField.hs index 7b63de3..0478e53 100644 --- a/lib/Database/PostgreSQL/Opium/FromField.hs +++ b/lib/Database/PostgreSQL/Opium/FromField.hs @@ -85,3 +85,15 @@ instance FromField Double where fromField = fromParser (Oid.real \/ Oid.doublePrecision) floatParser + +boolParser :: Parser Bool +boolParser = choice + [ string "t" $> True + , string "f" $> False + ] + +-- | See https://www.postgresql.org/docs/current/datatype-boolean.html. +instance FromField Bool where + fromField = fromParser + Oid.boolean + boolParser diff --git a/lib/Database/PostgreSQL/Opium/Oid.hs b/lib/Database/PostgreSQL/Opium/Oid.hs index 86a3659..3ebe82b 100644 --- a/lib/Database/PostgreSQL/Opium/Oid.hs +++ b/lib/Database/PostgreSQL/Opium/Oid.hs @@ -39,3 +39,7 @@ real = eq $ Oid 700 -- | 64-bit IEEE float doublePrecision :: Oid -> Bool doublePrecision = eq $ Oid 701 + +-- | Boolean +boolean :: Oid -> Bool +boolean = eq $ Oid 16 diff --git a/test/Database/PostgreSQL/Opium/FromFieldSpec.hs b/test/Database/PostgreSQL/Opium/FromFieldSpec.hs index 150a68e..5a2968d 100644 --- a/test/Database/PostgreSQL/Opium/FromFieldSpec.hs +++ b/test/Database/PostgreSQL/Opium/FromFieldSpec.hs @@ -42,6 +42,12 @@ newtype ADouble = ADouble instance FromRow ADouble where +newtype ABool = ABool + { bool :: Bool + } deriving (Eq, Generic, Show) + +instance FromRow ABool where + shouldFetch :: (Eq a, FromRow a, Show a) => Connection -> ByteString -> [a] -> IO () shouldFetch conn query expectedRows = do actualRows <- Opium.fetch_ conn query @@ -125,3 +131,16 @@ spec = do Right [ADouble value1] <- Opium.fetch_ conn "SELECT '-inf'::double precision AS double" value1 `shouldSatisfy` (isInfinite /\ (< 0)) + + describe "FromField Bool" $ do + it "Decodes boolean" $ \conn -> do + shouldFetch conn "SELECT true AS bool" [ABool True] + shouldFetch conn "SELECT 't'::boolean AS bool" [ABool True] + shouldFetch conn "SELECT 'yes'::boolean AS bool" [ABool True] + shouldFetch conn "SELECT 'on'::boolean AS bool" [ABool True] + shouldFetch conn "SELECT 1::boolean AS bool" [ABool True] + shouldFetch conn "SELECT false AS bool" [ABool False] + shouldFetch conn "SELECT 'f'::boolean AS bool" [ABool False] + shouldFetch conn "SELECT 'no'::boolean AS bool" [ABool False] + shouldFetch conn "SELECT 'off'::boolean AS bool" [ABool False] + shouldFetch conn "SELECT 0::boolean AS bool" [ABool False]