Skip to content

Commit fb43fcc

Browse files
authored
Merge pull request #2415 from digitallyinduced/refactor/use-isscalar-for-decoders
Generalize Id' hasql codec, replace HasqlDecodeValue with IsScalar
2 parents 8187f98 + 5684314 commit fb43fcc

File tree

1 file changed

+15
-37
lines changed

1 file changed

+15
-37
lines changed

ihp/IHP/Hasql/FromRow.hs

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
2+
{-# OPTIONS_GHC -Wno-orphans #-}
23
{-|
34
Module: IHP.Hasql.FromRow
45
Description: Typeclass for decoding hasql result rows
@@ -14,22 +15,12 @@ Also provides parser functions used by the generated decoders for custom Postgre
1415
-}
1516
module IHP.Hasql.FromRow
1617
( FromRowHasql (..)
17-
, HasqlDecodeValue (..)
1818
, HasqlDecodeColumn (..)
1919
) where
2020

2121
import Prelude
22-
import Data.ByteString (ByteString)
23-
import Data.Text (Text)
24-
import Data.UUID (UUID)
25-
import Data.Time.Clock (UTCTime, DiffTime)
26-
import Data.Time.Calendar (Day)
27-
import Data.Time.LocalTime (TimeOfDay)
2822
import qualified Hasql.Decoders as Decoders
2923
import qualified Hasql.Mapping.IsScalar as Mapping
30-
import Data.Int (Int16, Int32, Int64)
31-
import Data.Scientific (Scientific)
32-
import qualified Data.Aeson as Aeson
3324
import qualified Database.PostgreSQL.Simple.Types as PG
3425
import IHP.ModelSupport.Types (LabeledData(..), Id'(..), PrimaryKey)
3526

@@ -42,37 +33,24 @@ class FromRowHasql a where
4233
-- | Decoder for a single row
4334
hasqlRowDecoder :: Decoders.Row a
4435

45-
-- | Typeclass mapping Haskell scalar types to hasql value decoders
46-
class HasqlDecodeValue a where
47-
hasqlDecodeValue :: Decoders.Value a
48-
49-
instance HasqlDecodeValue Int16 where hasqlDecodeValue = Decoders.int2
50-
instance HasqlDecodeValue Int32 where hasqlDecodeValue = Decoders.int4
51-
instance HasqlDecodeValue Int64 where hasqlDecodeValue = Decoders.int8
52-
instance HasqlDecodeValue Int where hasqlDecodeValue = fromIntegral <$> Decoders.int8
53-
instance HasqlDecodeValue Bool where hasqlDecodeValue = Decoders.bool
54-
instance HasqlDecodeValue Text where hasqlDecodeValue = Decoders.text
55-
instance HasqlDecodeValue ByteString where hasqlDecodeValue = Decoders.bytea
56-
instance HasqlDecodeValue UUID where hasqlDecodeValue = Decoders.uuid
57-
instance HasqlDecodeValue UTCTime where hasqlDecodeValue = Decoders.timestamptz
58-
instance HasqlDecodeValue Day where hasqlDecodeValue = Decoders.date
59-
instance HasqlDecodeValue TimeOfDay where hasqlDecodeValue = Decoders.time
60-
instance HasqlDecodeValue DiffTime where hasqlDecodeValue = Decoders.interval
61-
instance HasqlDecodeValue Scientific where hasqlDecodeValue = Decoders.numeric
62-
instance HasqlDecodeValue Double where hasqlDecodeValue = Decoders.float8
63-
instance HasqlDecodeValue Float where hasqlDecodeValue = Decoders.float4
64-
instance HasqlDecodeValue Aeson.Value where hasqlDecodeValue = Decoders.jsonb
65-
instance Mapping.IsScalar (PrimaryKey table) => HasqlDecodeValue (Id' table) where hasqlDecodeValue = Id <$> Mapping.decoder
66-
67-
-- | Typeclass for building column-level row decoders, handling nullable/non-nullable
36+
-- | Typeclass for building column-level row decoders, handling nullable/non-nullable.
37+
-- Uses 'Mapping.IsScalar' from hasql-mapping for value-level decoding.
6838
class HasqlDecodeColumn a where
6939
hasqlColumnDecoder :: Decoders.Row a
7040

71-
instance {-# OVERLAPPABLE #-} HasqlDecodeValue a => HasqlDecodeColumn a where
72-
hasqlColumnDecoder = Decoders.column (Decoders.nonNullable hasqlDecodeValue)
41+
instance {-# OVERLAPPABLE #-} Mapping.IsScalar a => HasqlDecodeColumn a where
42+
hasqlColumnDecoder = Decoders.column (Decoders.nonNullable Mapping.decoder)
7343

74-
instance {-# OVERLAPPING #-} HasqlDecodeValue a => HasqlDecodeColumn (Maybe a) where
75-
hasqlColumnDecoder = Decoders.column (Decoders.nullable hasqlDecodeValue)
44+
instance {-# OVERLAPPING #-} Mapping.IsScalar a => HasqlDecodeColumn (Maybe a) where
45+
hasqlColumnDecoder = Decoders.column (Decoders.nullable Mapping.decoder)
46+
47+
-- | Decode 'Id' table' by decoding the primary key type and wrapping with 'Id'
48+
instance {-# OVERLAPPING #-} Mapping.IsScalar (PrimaryKey table) => HasqlDecodeColumn (Id' table) where
49+
hasqlColumnDecoder = Decoders.column (Decoders.nonNullable (Id <$> Mapping.decoder))
50+
51+
-- | Decode 'Maybe (Id' table)' for nullable foreign keys
52+
instance {-# OVERLAPPING #-} Mapping.IsScalar (PrimaryKey table) => HasqlDecodeColumn (Maybe (Id' table)) where
53+
hasqlColumnDecoder = Decoders.column (Decoders.nullable (Id <$> Mapping.decoder))
7654

7755
-- FromRowHasql instances for PG.Only and tuples (used by sqlQuery callers like fetchCount, fetchExists)
7856

0 commit comments

Comments
 (0)