Implement date -> Day decoding

This commit is contained in:
Paul Brinkmeier 2023-09-23 11:11:29 +02:00
parent 4d21e67130
commit 126b8ee6e9
6 changed files with 32 additions and 0 deletions

View File

@ -63,6 +63,7 @@ getScoreByAge conn = do
- [x] Implement `Float` and `Double` decoding - [x] Implement `Float` and `Double` decoding
- [x] Clean up and document column table stuff - [x] Clean up and document column table stuff
- [x] Decode `LibPQ.Binary` - [x] Decode `LibPQ.Binary`
- [x] Implement `date -> Day` decoding
- [ ] Implement `fetch` (`fetch_` but with parameter passing) - [ ] Implement `fetch` (`fetch_` but with parameter passing)
- [ ] Implement `UTCTime` and zoned time decoding - [ ] Implement `UTCTime` and zoned time decoding
- [ ] Implement JSON decoding - [ ] Implement JSON decoding

View File

@ -20,6 +20,7 @@
hspec hspec
postgresql-libpq postgresql-libpq
text text
time
transformers transformers
vector vector
])) ]))

View File

@ -11,7 +11,9 @@ import Data.Attoparsec.ByteString (Parser)
import Data.Bits (Bits (..)) import Data.Bits (Bits (..))
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Functor (($>)) import Data.Functor (($>))
import Data.Int (Int32)
import Data.Proxy (Proxy (..)) import Data.Proxy (Proxy (..))
import Data.Time (Day (..))
import Data.Text (Text) import Data.Text (Text)
import Data.Word (Word32, Word64) import Data.Word (Word32, Word64)
import Database.PostgreSQL.LibPQ (Oid) import Database.PostgreSQL.LibPQ (Oid)
@ -107,3 +109,11 @@ boolParser = AP.choice
instance FromField Bool where instance FromField Bool where
validOid Proxy = Oid.boolean validOid Proxy = Oid.boolean
parseField = boolParser parseField = boolParser
-- | See https://www.postgresql.org/docs/current/datatype-datetime.html.
-- Relevant as well: https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/adt/datetime.c;h=267dfd37b2e8b9bc63797c69b9ca2e45e6bfde61;hb=HEAD#l267.
instance FromField Day where
validOid Proxy = Oid.date
parseField = fromJulianDay . fromIntegral <$> intParser @Int32
where
fromJulianDay x = ModifiedJulianDay $ x + 51544

View File

@ -48,3 +48,7 @@ doublePrecision = eq $ Oid 701
-- | Boolean -- | Boolean
boolean :: Oid -> Bool boolean :: Oid -> Bool
boolean = eq $ Oid 16 boolean = eq $ Oid 16
-- | Single days/dates.
date :: Oid -> Bool
date = eq $ Oid 1082

View File

@ -79,6 +79,7 @@ library
containers, containers,
postgresql-libpq, postgresql-libpq,
text, text,
time,
transformers, transformers,
vector vector
@ -122,4 +123,5 @@ test-suite opium-test
bytestring, bytestring,
hspec, hspec,
postgresql-libpq, postgresql-libpq,
time,
text text

View File

@ -4,6 +4,7 @@
module Database.PostgreSQL.Opium.FromFieldSpec (spec) where module Database.PostgreSQL.Opium.FromFieldSpec (spec) where
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.Time (Day (..), fromGregorian)
import Data.Text (Text) import Data.Text (Text)
import Database.PostgreSQL.LibPQ (Connection) import Database.PostgreSQL.LibPQ (Connection)
import Database.PostgreSQL.Opium (FromRow) import Database.PostgreSQL.Opium (FromRow)
@ -72,6 +73,12 @@ newtype ABool = ABool
instance FromRow ABool where instance FromRow ABool where
newtype ADay = ADay
{ day :: Day
} deriving (Eq, Generic, Show)
instance FromRow ADay where
shouldFetch :: (Eq a, FromRow a, Show a) => Connection -> ByteString -> [a] -> IO () shouldFetch :: (Eq a, FromRow a, Show a) => Connection -> ByteString -> [a] -> IO ()
shouldFetch conn query expectedRows = do shouldFetch conn query expectedRows = do
actualRows <- Opium.fetch_ conn query actualRows <- Opium.fetch_ conn query
@ -200,3 +207,10 @@ spec = do
shouldFetch conn "SELECT 'no'::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 'off'::boolean AS bool" [ABool False]
shouldFetch conn "SELECT 0::boolean AS bool" [ABool False] shouldFetch conn "SELECT 0::boolean AS bool" [ABool False]
describe "FromField Day" $ do
it "Decodes date" $ \conn -> do
shouldFetch conn "SELECT date '1970-01-01' AS day" [ADay $ fromGregorian 1970 1 1]
shouldFetch conn "SELECT date '2023-09-23' AS day" [ADay $ fromGregorian 2023 9 23]
-- Example from postgres doc page
shouldFetch conn "SELECT date 'J2451187' AS day" [ADay $ fromGregorian 1999 1 8]