diff --git a/lib/Database/PostgreSQL/Opium/FromField.hs b/lib/Database/PostgreSQL/Opium/FromField.hs index 30b21c9..d87270e 100644 --- a/lib/Database/PostgreSQL/Opium/FromField.hs +++ b/lib/Database/PostgreSQL/Opium/FromField.hs @@ -41,6 +41,9 @@ import qualified Database.PostgreSQL.Opium.Oid as Oid (\/) :: (a -> Bool) -> (a -> Bool) -> a -> Bool p \/ q = \x -> p x || q x +eq :: Eq a => a -> a -> Bool +eq = (==) + fromField :: FromField a => ByteString -> Either String a fromField = AP.parseOnly parseField @@ -52,13 +55,13 @@ class FromField a where -- | See https://www.postgresql.org/docs/current/datatype-binary.html. -- Accepts @bytea@. instance FromField ByteString where - validOid Proxy = Oid.bytea + validOid Proxy = eq Oid.bytea parseField = AP.takeByteString -- | See https://www.postgresql.org/docs/current/datatype-character.html. -- Accepts @text@, @character@ and @character varying@. instance FromField Text where - validOid Proxy = Oid.text \/ Oid.character \/ Oid.characterVarying + validOid Proxy = eq Oid.text \/ eq Oid.character \/ eq Oid.characterVarying parseField = Encoding.decodeUtf8 <$> AP.takeByteString -- Accepts @text@, @character@ and @character varying@. @@ -98,22 +101,22 @@ readWord bs = case BS.length bs of -- | See https://www.postgresql.org/docs/current/datatype-numeric.html. -- We assume that 'Int' has 64 bits. This is not guaranteed but reasonable enough. instance FromField Int where - validOid Proxy = Oid.smallint \/ Oid.integer \/ Oid.bigint + validOid Proxy = eq Oid.smallint \/ eq Oid.integer \/ eq Oid.bigint parseField = readInt =<< AP.takeByteString -- | See https://www.postgresql.org/docs/current/datatype-numeric.html. instance FromField Integer where - validOid Proxy = Oid.smallint \/ Oid.integer \/ Oid.bigint + validOid Proxy = eq Oid.smallint \/ eq Oid.integer \/ eq Oid.bigint parseField = readInt =<< AP.takeByteString instance FromField Word where - validOid Proxy = Oid.smallint \/ Oid.integer \/ Oid.bigint + validOid Proxy = eq Oid.smallint \/ eq Oid.integer \/ eq Oid.bigint parseField = readWord =<< AP.takeByteString -- | See https://www.postgresql.org/docs/current/datatype-numeric.html. -- Accepts only @real@ fields, not @double precision@. instance FromField Float where - validOid Proxy = Oid.real + validOid Proxy = eq Oid.real -- Afaict there's no cleaner (@base@) way to access the underlying bits. -- In C we'd do -- @@ -125,7 +128,7 @@ instance FromField Float where -- | See https://www.postgresql.org/docs/current/datatype-numeric.html. -- Accepts only @double precision@ fields, not @real@. instance FromField Double where - validOid Proxy = Oid.doublePrecision + validOid Proxy = eq Oid.doublePrecision parseField = unsafeCoerce <$> readBigEndian @Word <$> AP.takeByteString boolParser :: Parser Bool @@ -136,7 +139,7 @@ boolParser = AP.choice -- | See https://www.postgresql.org/docs/current/datatype-boolean.html. instance FromField Bool where - validOid Proxy = Oid.boolean + validOid Proxy = eq Oid.boolean parseField = boolParser postgresEpoch :: Day @@ -151,14 +154,14 @@ fromPostgresJulian x = addDays x postgresEpoch -- In short, Postgres treats 1 BC as a leap year and doesn't have a year zero. -- This means that working with negative dates will be different in Postgres and your application code. instance FromField Day where - validOid Proxy = Oid.date + validOid Proxy = eq Oid.date parseField = fromPostgresJulian . fromIntegral <$> readBigEndian @Int32 <$> AP.takeByteString -- | See https://www.postgresql.org/docs/current/datatype-datetime.html. -- Binary format: https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/adt/date.c;h=ae0f24de2c3c54eb6d0405cdb212597c2407238e;hb=HEAD#l1542. -- Accepts @time@. instance FromField DiffTime where - validOid Proxy = Oid.time + validOid Proxy = eq Oid.time parseField = microsecondsToDiffTime . fromIntegral <$> readBigEndian @Int <$> AP.takeByteString where microsecondsToDiffTime :: Integer -> DiffTime @@ -168,7 +171,7 @@ instance FromField DiffTime where -- Binary format: https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/adt/date.c;h=ae0f24de2c3c54eb6d0405cdb212597c2407238e;hb=HEAD#l1542. -- Accepts @time@. instance FromField TimeOfDay where - validOid Proxy = Oid.time + validOid Proxy = eq Oid.time parseField = timeToTimeOfDay <$> parseField @DiffTime fromPostgresTimestamp :: Int -> (Day, DiffTime) @@ -181,7 +184,7 @@ fromPostgresTimestamp ts = (day, time) -- | See https://www.postgresql.org/docs/current/datatype-datetime.html. -- Accepts @timestamp with timezone@. instance FromField UTCTime where - validOid Proxy = Oid.timestampWithTimezone + validOid Proxy = eq Oid.timestampWithTimezone parseField = toUTCTime . fromPostgresTimestamp <$> readBigEndian @Int <$> AP.takeByteString where toUTCTime (day, time) = UTCTime day time diff --git a/lib/Database/PostgreSQL/Opium/Oid.hs b/lib/Database/PostgreSQL/Opium/Oid.hs index 83399ec..c5cc748 100644 --- a/lib/Database/PostgreSQL/Opium/Oid.hs +++ b/lib/Database/PostgreSQL/Opium/Oid.hs @@ -2,65 +2,62 @@ module Database.PostgreSQL.Opium.Oid where import Database.PostgreSQL.LibPQ (Oid (..)) -eq :: Eq a => a -> a -> Bool -eq = (==) - -- raw byte string -bytea :: Oid -> Bool -bytea = eq $ Oid 17 +bytea :: Oid +bytea = Oid 17 -- string types -text :: Oid -> Bool -text = eq $ Oid 25 +text :: Oid +text = Oid 25 -character :: Oid -> Bool -character = eq $ Oid 1042 +character :: Oid +character = Oid 1042 -characterVarying :: Oid -> Bool -characterVarying = eq $ Oid 1043 +characterVarying :: Oid +characterVarying = Oid 1043 -- integer types -- | 16-bit integer -smallint :: Oid -> Bool -smallint = eq $ Oid 21 +smallint :: Oid +smallint = Oid 21 -- | 32-bit integer -integer :: Oid -> Bool -integer = eq $ Oid 23 +integer :: Oid +integer = Oid 23 -- | 64-bit integer -bigint :: Oid -> Bool -bigint = eq $ Oid 20 +bigint :: Oid +bigint = Oid 20 -- floating point types -- | 32-bit IEEE float -real :: Oid -> Bool -real = eq $ Oid 700 +real :: Oid +real = Oid 700 -- | 64-bit IEEE float -doublePrecision :: Oid -> Bool -doublePrecision = eq $ Oid 701 +doublePrecision :: Oid +doublePrecision = Oid 701 --- | Boolean -boolean :: Oid -> Bool -boolean = eq $ Oid 16 +-- | Oid +boolean :: Oid +boolean = Oid 16 -- | Single days/dates. -date :: Oid -> Bool -date = eq $ Oid 1082 +date :: Oid +date = Oid 1082 -- | Time of day. -time :: Oid -> Bool -time = eq $ Oid 1083 +time :: Oid +time = Oid 1083 -- | A point in time. -timestamp :: Oid -> Bool -timestamp = eq $ Oid 1114 +timestamp :: Oid +timestamp = Oid 1114 -- | A point in time. -timestampWithTimezone :: Oid -> Bool -timestampWithTimezone = eq $ Oid 1184 +timestampWithTimezone :: Oid +timestampWithTimezone = Oid 1184