Skip to content

Commit 46b17fa

Browse files
Decoders prototype
1 parent 320380f commit 46b17fa

File tree

2 files changed

+132
-1
lines changed

2 files changed

+132
-1
lines changed

src/Database/PostgreSQL/Decoders.hs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
-- High level
2+
--
3+
4+
class PrimField a where
5+
6+
primField :: RowDecoder r => FieldF r a
7+
8+
{-# INLINE field #-}
9+
field :: RowDecoder r => r a
10+
field = getRowNonNullValue $ getFieldDec primField
11+
12+
type IsArrayField a :: Bool
13+
type IsArrayField a = 'False
14+
15+
type IsNullableField a :: Bool
16+
type IsNullableField a = 'False
17+
18+
type IsPrimitiveField a :: Bool
19+
type IsPrimitiveField a = 'True
20+
21+
content :: IsPrimitiveField a ~ 'True => a
22+
content = undefined
23+
24+
arrayDim :: Proxy a -> Int
25+
arrayDim _ = 0
26+
27+
asArrayData :: V.Vector Int -> Decode a
28+
asArrayData _ = runRowDecoder (field :: RowValue a)
29+
30+
instance PrimField Int16 where
31+
primField = Single int2
32+
33+
instance PrimField Int32 where
34+
primField = Single int4
35+
36+
instance PrimField Int64 where
37+
primField = Single int8
38+
39+
instance PrimField Bool where
40+
primField = Single bool
41+
42+
instance PrimField B.ByteString where
43+
primField = Single getByteString
44+
45+
instance PrimField a => PrimField (Maybe a) where
46+
primField = undefined
47+
content = undefined
48+
49+
type IsPrimitiveField (Maybe a) = 'False
50+
type IsNullableField (Maybe a) = 'True
51+
type IsArrayField (Maybe a) = IsArrayField a
52+
{-# INLINE field #-}
53+
field = getRowNullValue $ getFieldDec primField
54+
55+
instance (IsAllowedArray (IsNullableField a) (IsArrayField a) ~ 'True,
56+
PrimField a)
57+
=> PrimField (V.Vector a) where
58+
primField = Single $ arrayFieldDecoder
59+
(arrayDim (Proxy :: Proxy (V.Vector a)))
60+
asArrayData
61+
62+
type IsArrayField (V.Vector a) = 'True
63+
arrayDim _ = arrayDim (Proxy :: Proxy a) + 1
64+
65+
asArrayData vec = V.replicateM (vec V.! arrayDim (Proxy :: Proxy a))
66+
$ asArrayData vec
67+
68+
type family IsAllowedArray (n :: Bool) (a :: Bool) :: Bool where
69+
IsAllowedArray 'True 'True = 'False
70+
IsAllowedArray _ _ = 'True
71+
72+
73+
-- TODO add array value
74+
newtype RowValue a = RowValue { unRowValue :: Decode a }
75+
deriving (Functor, Applicative, Monad)
76+
newtype CompositeValue a = CompositeValue { unCompositeValue :: Decode a }
77+
deriving (Functor, Applicative, Monad)
78+
79+
class (Functor r, Applicative r, Monad r) => RowDecoder r where
80+
getRowNonNullValue :: FieldDecoder a -> r a
81+
getRowNullValue :: FieldDecoder a -> r (Maybe a)
82+
runRowDecoder :: r a -> Decode a
83+
84+
instance RowDecoder RowValue where
85+
{-# INLINE getRowNonNullValue #-}
86+
getRowNonNullValue = RowValue . getNonNullable
87+
{-# INLINE getRowNullValue #-}
88+
getRowNullValue = RowValue . getNullable
89+
{-# INLINE runRowDecoder #-}
90+
runRowDecoder = unRowValue
91+
92+
instance RowDecoder CompositeValue where
93+
{-# INLINE getRowNonNullValue #-}
94+
getRowNonNullValue = CompositeValue
95+
. fmap (compositeValue *>) getNonNullable
96+
{-# INLINE getRowNullValue #-}
97+
getRowNullValue = CompositeValue
98+
. fmap (compositeValue *>) getNullable
99+
{-# INLINE runRowDecoder #-}
100+
runRowDecoder = unCompositeValue
101+
102+
instance (PrimField a1, PrimField a2, PrimField a3)
103+
=> PrimField (a1, a2, a3) where
104+
105+
{-# INLINE primField #-}
106+
primField = Row $ (,,) <$> field <*> field <*> field
107+
108+
instance (PrimField a1, PrimField a2, PrimField a3, PrimField a4,
109+
PrimField a5, PrimField a6, PrimField a7, PrimField a8,
110+
PrimField a9, PrimField a10, PrimField a11, PrimField a12)
111+
=> PrimField (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
112+
where
113+
{-# INLINE primField #-}
114+
primField = Row $ (,,,,,,,,,,,) <$> field <*> field <*> field <*> field
115+
<*> field <*> field <*> field <*> field
116+
<*> field <*> field <*> field <*> field
117+
118+
119+
composite :: CompositeValue a -> FieldDecoder a
120+
composite dec _ = compositeHeader *> runRowDecoder dec
121+
122+
{-# INLINE rowDecoder #-}
123+
rowDecoder :: forall a. PrimField a => Decode a
124+
rowDecoder = case primField of
125+
Single f -> skipDataRowHeader *> runRowDecoder
126+
(getRowNonNullValue f :: RowValue a)
127+
Row r -> skipDataRowHeader *> runRowDecoder (r :: RowValue a)
128+

src/Database/PostgreSQL/Query.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ import Database.PostgreSQL.Other
2020
-- Row parser
2121
---------------------
2222
data RowParserError = RowParserError
23-
data RowParser s a = RowParser (s -> Either RowParserError (s, a))
23+
data RowParser s a
24+
= PrimParser (B.ByteString -> Either RowParserError (B.ByteString, a))
25+
| ArrayParser (B.ByteString -> Either RowParserError (B.ByteString, a))
26+
| RowParser (s -> Either RowParserError (s, a))
2427

2528
--------------------
2629
-- Encoders

0 commit comments

Comments
 (0)