@@ -1,4 +1,6 @@
1−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE FlexibleContexts #-}
2+{-# LANGUAGE RecordWildCards, FlexibleInstances, DefaultSignatures #-}
3------------------------------------------------------------------------------
5------------------------------------------------------------------------------
@@ -7,13 +9,15 @@
7-- License: BSD3
9-- License: BSD3
8-- Maintainer: Leon P Smith <leon@melding-monads.com>
10-- Maintainer: Leon P Smith <leon@melding-monads.com>
9-- Stability: experimental
11-- Stability: experimental
10−-- Portability: portable
12-- The 'FromRow' typeclass, for converting a row of results
13-- The 'FromRow' typeclass, for converting a row of results
13-- returned by a SQL query into a more useful Haskell representation.
14-- returned by a SQL query into a more useful Haskell representation.
15-- Predefined instances are provided for tuples containing up to ten
16-- Predefined instances are provided for tuples containing up to ten
16−-- elements.
17+-- elements. The instances for 'Maybe' types return 'Nothing' if all
18+-- the columns that would have been otherwise consumed are null, otherwise
19+-- it attempts a regular conversion.
17------------------------------------------------------------------------------
21------------------------------------------------------------------------------
19module Database.PostgreSQL.Simple.FromRow
23module Database.PostgreSQL.Simple.FromRow
@@ -24,32 +28,36 @@ module Database.PostgreSQL.Simple.FromRow
24 , numFieldsRemaining
28 , numFieldsRemaining
31+import Prelude hiding (null)
27−import Control.Applicative (Applicative(..), (<$>))
32+import Control.Applicative (Applicative(..), (<$>), (<|>), (*>), liftA2)
28−import Control.Monad (replicateM)
33+import Control.Monad (replicateM, replicateM_)
34+import Control.Monad.Trans.State.Strict
35+import Control.Monad.Trans.Reader
36+import Control.Monad.Trans.Class
29−import Data.ByteString (ByteString)
37+import Data.ByteString (ByteString)
30import qualified Data.ByteString.Char8 as B
38import qualified Data.ByteString.Char8 as B
39+import Data.Vector (Vector)
40+import qualified Data.Vector as V
31−import Database.PostgreSQL.Simple.Types (Only(..))
41+import Database.PostgreSQL.Simple.Types (Only(..))
32import qualified Database.PostgreSQL.LibPQ as PQ
42import qualified Database.PostgreSQL.LibPQ as PQ
33import Database.PostgreSQL.Simple.Internal
43import Database.PostgreSQL.Simple.Internal
44+import Database.PostgreSQL.Simple.Compat
34import Database.PostgreSQL.Simple.FromField
45import Database.PostgreSQL.Simple.FromField
35import Database.PostgreSQL.Simple.Ok
46import Database.PostgreSQL.Simple.Ok
36−import Database.PostgreSQL.Simple.Types ((:.)(..))
47+import Database.PostgreSQL.Simple.Types ((:.)(..), Null)
37import Database.PostgreSQL.Simple.TypeInfo
48import Database.PostgreSQL.Simple.TypeInfo
38−import System.IO.Unsafe (unsafePerformIO)
40−import Control.Monad.Trans.State.Strict
50+import GHC.Generics
41−import Control.Monad.Trans.Reader
42−import Control.Monad.Trans.Class
44−import Data.Vector ((!))
46-- | A collection type that can be converted from a sequence of fields.
53-- | A collection type that can be converted from a sequence of fields.
47-- Instances are provided for tuples up to 10 elements and lists of any length.
54-- Instances are provided for tuples up to 10 elements and lists of any length.
49−-- Note that instances can defined outside of postgresql-simple, which is
56+-- Note that instances can be defined outside of postgresql-simple, which is
50-- often useful. For example, here's an instance for a user-defined pair:
57-- often useful. For example, here's an instance for a user-defined pair:
52−-- @data User = User { name :: String, fileQuota :: Int }
60+-- data User = User { name :: String, fileQuota :: Int }
54-- instance 'FromRow' User where
62-- instance 'FromRow' User where
55-- fromRow = User \<$\> 'field' \<*\> 'field'
63-- fromRow = User \<$\> 'field' \<*\> 'field'
@@ -59,27 +67,47 @@ import Data.Vector ((!))
59-- in a single row of the query result. Otherwise, a 'ConversionFailed'
67-- in a single row of the query result. Otherwise, a 'ConversionFailed'
60-- exception will be thrown.
68-- exception will be thrown.
70+-- You can also derive 'FromRow' for your data type using GHC generics, like
74+-- \{-# LANGUAGE DeriveAnyClass \#-}
75+-- \{-# LANGUAGE DeriveGeneric \#-}
77+-- import "GHC.Generics" ('GHC.Generics.Generic')
78+-- import "Database.PostgreSQL.Simple" ('FromRow')
80+-- data User = User { name :: String, fileQuota :: Int }
81+-- deriving ('GHC.Generics.Generic', 'FromRow')
84+-- Note that this only works for product types (e.g. records) and does not
85+-- support sum types or recursive types.
62−-- Note that 'field' evaluates it's result to WHNF, so the caveats listed in
87+-- Note that 'field' evaluates its result to WHNF, so the caveats listed in
63−-- previous versions of postgresql-simple no longer apply. Instead, look
88+-- mysql-simple and very early versions of postgresql-simple no longer apply.
64−-- at the caveats associated with user-defined implementations of 'fromRow'.
89+-- Instead, look at the caveats associated with user-defined implementations
66class FromRow a where
92class FromRow a where
67 fromRow :: RowParser a
93 fromRow :: RowParser a
94+ default fromRow :: (Generic a, GFromRow (Rep a)) => RowParser a
95+ fromRow = to <$> gfromRow
69getvalue :: PQ.Result -> PQ.Row -> PQ.Column -> Maybe ByteString
97getvalue :: PQ.Result -> PQ.Row -> PQ.Column -> Maybe ByteString
70−getvalue result row col = unsafePerformIO (PQ.getvalue result row col)
98+getvalue result row col = unsafeDupablePerformIO (PQ.getvalue' result row col)
72nfields :: PQ.Result -> PQ.Column
100nfields :: PQ.Result -> PQ.Column
73−nfields result = unsafePerformIO (PQ.nfields result)
101+nfields result = unsafeDupablePerformIO (PQ.nfields result)
75getTypeInfoByCol :: Row -> PQ.Column -> Conversion TypeInfo
103getTypeInfoByCol :: Row -> PQ.Column -> Conversion TypeInfo
76−getTypeInfoByCol Row{..} col =
104+getTypeInfoByCol Row{..} col =
77 Conversion $ \conn -> do
105 Conversion $ \conn -> do
78 oid <- PQ.ftype rowresult col
106 oid <- PQ.ftype rowresult col
79 Ok <$> getTypeInfo conn oid
107 Ok <$> getTypeInfo conn oid
81getTypenameByCol :: Row -> PQ.Column -> Conversion ByteString
109getTypenameByCol :: Row -> PQ.Column -> Conversion ByteString
82−getTypenameByCol row col = typname . typ <$> getTypeInfoByCol row col
110+getTypenameByCol row col = typname <$> getTypeInfoByCol row col
84fieldWith :: FieldParser a -> RowParser a
112fieldWith :: FieldParser a -> RowParser a
85fieldWith fieldP = RP $ do
113fieldWith fieldP = RP $ do
@@ -92,7 +120,7 @@ fieldWith fieldP = RP $ do
92 then lift $ lift $ do
120 then lift $ lift $ do
93 vals <- mapM (getTypenameByCol r) [0..ncols-1]
121 vals <- mapM (getTypenameByCol r) [0..ncols-1]
94 let err = ConversionFailed
122 let err = ConversionFailed
95− (show (unCol ncols) ++ " values: " ++ show vals)
123+ (show (unCol ncols) ++ " values: " ++ show (map ellipsis vals))
98 ("at least " ++ show (unCol column + 1)
126 ("at least " ++ show (unCol column + 1)
@@ -101,9 +129,10 @@ fieldWith fieldP = RP $ do
101 \convert and number in target type"
129 \convert and number in target type"
102 conversionError err
130 conversionError err
104− let result = rowresult
132+ let !result = rowresult
133+ !typeOid = unsafeDupablePerformIO (PQ.ftype result column)
105− field = Field{..}
134+ !field' = Field{..}
106− lift (lift (fieldP field (getvalue result row column)))
135+ lift (lift (fieldP field' (getvalue result row column)))
108field :: FromField a => RowParser a
137field :: FromField a => RowParser a
109field = fieldWith fromField
138field = fieldWith fromField
@@ -119,57 +148,340 @@ numFieldsRemaining = RP $ do
119 column <- lift get
148 column <- lift get
120 return $! (\(PQ.Col x) -> fromIntegral x) (nfields rowresult - column)
149 return $! (\(PQ.Col x) -> fromIntegral x) (nfields rowresult - column)
151+null :: RowParser Null
122instance (FromField a) => FromRow (Only a) where
154instance (FromField a) => FromRow (Only a) where
123 fromRow = Only <$> field
155 fromRow = Only <$> field
157+instance (FromField a) => FromRow (Maybe (Only a)) where
158+ fromRow = (null *> pure Nothing)
159+ <|> (Just <$> fromRow)
125instance (FromField a, FromField b) => FromRow (a,b) where
161instance (FromField a, FromField b) => FromRow (a,b) where
126 fromRow = (,) <$> field <*> field
162 fromRow = (,) <$> field <*> field
164+instance (FromField a, FromField b) => FromRow (Maybe (a,b)) where
165+ fromRow = (null *> null *> pure Nothing)
166+ <|> (Just <$> fromRow)
128instance (FromField a, FromField b, FromField c) => FromRow (a,b,c) where
168instance (FromField a, FromField b, FromField c) => FromRow (a,b,c) where
129 fromRow = (,,) <$> field <*> field <*> field
169 fromRow = (,,) <$> field <*> field <*> field
171+instance (FromField a, FromField b, FromField c) => FromRow (Maybe (a,b,c)) where
172+ fromRow = (null *> null *> null *> pure Nothing)
173+ <|> (Just <$> fromRow)
131instance (FromField a, FromField b, FromField c, FromField d) =>
175instance (FromField a, FromField b, FromField c, FromField d) =>
132 FromRow (a,b,c,d) where
176 FromRow (a,b,c,d) where
133 fromRow = (,,,) <$> field <*> field <*> field <*> field
177 fromRow = (,,,) <$> field <*> field <*> field <*> field
179+instance (FromField a, FromField b, FromField c, FromField d) =>
180+ FromRow (Maybe (a,b,c,d)) where
181+ fromRow = (null *> null *> null *> null *> pure Nothing)
182+ <|> (Just <$> fromRow)
135instance (FromField a, FromField b, FromField c, FromField d, FromField e) =>
184instance (FromField a, FromField b, FromField c, FromField d, FromField e) =>
136 FromRow (a,b,c,d,e) where
185 FromRow (a,b,c,d,e) where
137 fromRow = (,,,,) <$> field <*> field <*> field <*> field <*> field
186 fromRow = (,,,,) <$> field <*> field <*> field <*> field <*> field
188+instance (FromField a, FromField b, FromField c, FromField d, FromField e) =>
189+ FromRow (Maybe (a,b,c,d,e)) where
190+ fromRow = (null *> null *> null *> null *> null *> pure Nothing)
191+ <|> (Just <$> fromRow)
139instance (FromField a, FromField b, FromField c, FromField d, FromField e,
193instance (FromField a, FromField b, FromField c, FromField d, FromField e,
140 FromField f) =>
194 FromField f) =>
141 FromRow (a,b,c,d,e,f) where
195 FromRow (a,b,c,d,e,f) where
142 fromRow = (,,,,,) <$> field <*> field <*> field <*> field <*> field
196 fromRow = (,,,,,) <$> field <*> field <*> field <*> field <*> field
143 <*> field
197 <*> field
199+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
201+ FromRow (Maybe (a,b,c,d,e,f)) where
202+ fromRow = (null *> null *> null *> null *> null *>
203+ null *> pure Nothing)
204+ <|> (Just <$> fromRow)
145instance (FromField a, FromField b, FromField c, FromField d, FromField e,
206instance (FromField a, FromField b, FromField c, FromField d, FromField e,
146 FromField f, FromField g) =>
207 FromField f, FromField g) =>
147 FromRow (a,b,c,d,e,f,g) where
208 FromRow (a,b,c,d,e,f,g) where
148 fromRow = (,,,,,,) <$> field <*> field <*> field <*> field <*> field
209 fromRow = (,,,,,,) <$> field <*> field <*> field <*> field <*> field
149 <*> field <*> field
210 <*> field <*> field
212+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
213+ FromField f, FromField g) =>
214+ FromRow (Maybe (a,b,c,d,e,f,g)) where
215+ fromRow = (null *> null *> null *> null *> null *>
216+ null *> null *> pure Nothing)
217+ <|> (Just <$> fromRow)
151instance (FromField a, FromField b, FromField c, FromField d, FromField e,
219instance (FromField a, FromField b, FromField c, FromField d, FromField e,
152 FromField f, FromField g, FromField h) =>
220 FromField f, FromField g, FromField h) =>
153 FromRow (a,b,c,d,e,f,g,h) where
221 FromRow (a,b,c,d,e,f,g,h) where
154 fromRow = (,,,,,,,) <$> field <*> field <*> field <*> field <*> field
222 fromRow = (,,,,,,,) <$> field <*> field <*> field <*> field <*> field
155 <*> field <*> field <*> field
223 <*> field <*> field <*> field
225+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
226+ FromField f, FromField g, FromField h) =>
227+ FromRow (Maybe (a,b,c,d,e,f,g,h)) where
228+ fromRow = (null *> null *> null *> null *> null *>
229+ null *> null *> null *> pure Nothing)
230+ <|> (Just <$> fromRow)
157instance (FromField a, FromField b, FromField c, FromField d, FromField e,
232instance (FromField a, FromField b, FromField c, FromField d, FromField e,
158 FromField f, FromField g, FromField h, FromField i) =>
233 FromField f, FromField g, FromField h, FromField i) =>
159 FromRow (a,b,c,d,e,f,g,h,i) where
234 FromRow (a,b,c,d,e,f,g,h,i) where
160 fromRow = (,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
235 fromRow = (,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
161 <*> field <*> field <*> field <*> field
236 <*> field <*> field <*> field <*> field
238+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
239+ FromField f, FromField g, FromField h, FromField i) =>
240+ FromRow (Maybe (a,b,c,d,e,f,g,h,i)) where
241+ fromRow = (null *> null *> null *> null *> null *>
242+ null *> null *> null *> null *> pure Nothing)
243+ <|> (Just <$> fromRow)
163instance (FromField a, FromField b, FromField c, FromField d, FromField e,
245instance (FromField a, FromField b, FromField c, FromField d, FromField e,
164 FromField f, FromField g, FromField h, FromField i, FromField j) =>
246 FromField f, FromField g, FromField h, FromField i, FromField j) =>
165 FromRow (a,b,c,d,e,f,g,h,i,j) where
247 FromRow (a,b,c,d,e,f,g,h,i,j) where
166 fromRow = (,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
248 fromRow = (,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
167 <*> field <*> field <*> field <*> field <*> field
249 <*> field <*> field <*> field <*> field <*> field
251+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
252+ FromField f, FromField g, FromField h, FromField i, FromField j) =>
253+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j)) where
254+ fromRow = (null *> null *> null *> null *> null *>
255+ null *> null *> null *> null *> null *> pure Nothing)
256+ <|> (Just <$> fromRow)
258+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
259+ FromField f, FromField g, FromField h, FromField i, FromField j,
261+ FromRow (a,b,c,d,e,f,g,h,i,j,k) where
262+ fromRow = (,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
263+ <*> field <*> field <*> field <*> field <*> field
266+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
267+ FromField f, FromField g, FromField h, FromField i, FromField j,
269+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k)) where
270+ fromRow = (null *> null *> null *> null *> null *>
271+ null *> null *> null *> null *> null *>
272+ null *> pure Nothing)
273+ <|> (Just <$> fromRow)
275+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
276+ FromField f, FromField g, FromField h, FromField i, FromField j,
277+ FromField k, FromField l) =>
278+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l) where
279+ fromRow = (,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
280+ <*> field <*> field <*> field <*> field <*> field
283+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
284+ FromField f, FromField g, FromField h, FromField i, FromField j,
285+ FromField k, FromField l) =>
286+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l)) where
287+ fromRow = (null *> null *> null *> null *> null *>
288+ null *> null *> null *> null *> null *>
289+ null *> null *> pure Nothing)
290+ <|> (Just <$> fromRow)
292+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
293+ FromField f, FromField g, FromField h, FromField i, FromField j,
294+ FromField k, FromField l, FromField m) =>
295+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m) where
296+ fromRow = (,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
297+ <*> field <*> field <*> field <*> field <*> field
298+ <*> field <*> field <*> field
300+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
301+ FromField f, FromField g, FromField h, FromField i, FromField j,
302+ FromField k, FromField l, FromField m) =>
303+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m)) where
304+ fromRow = (null *> null *> null *> null *> null *>
305+ null *> null *> null *> null *> null *>
306+ null *> null *> null *> pure Nothing)
307+ <|> (Just <$> fromRow)
309+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
310+ FromField f, FromField g, FromField h, FromField i, FromField j,
311+ FromField k, FromField l, FromField m, FromField n) =>
312+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n) where
313+ fromRow = (,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
314+ <*> field <*> field <*> field <*> field <*> field
315+ <*> field <*> field <*> field <*> field
317+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
318+ FromField f, FromField g, FromField h, FromField i, FromField j,
319+ FromField k, FromField l, FromField m, FromField n) =>
320+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n)) where
321+ fromRow = (null *> null *> null *> null *> null *>
322+ null *> null *> null *> null *> null *>
323+ null *> null *> null *> null *> pure Nothing)
324+ <|> (Just <$> fromRow)
326+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
327+ FromField f, FromField g, FromField h, FromField i, FromField j,
328+ FromField k, FromField l, FromField m, FromField n, FromField o) =>
329+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) where
330+ fromRow = (,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
331+ <*> field <*> field <*> field <*> field <*> field
332+ <*> field <*> field <*> field <*> field <*> field
334+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
335+ FromField f, FromField g, FromField h, FromField i, FromField j,
336+ FromField k, FromField l, FromField m, FromField n, FromField o) =>
337+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)) where
338+ fromRow = (null *> null *> null *> null *> null *>
339+ null *> null *> null *> null *> null *>
340+ null *> null *> null *> null *> null *> pure Nothing)
341+ <|> (Just <$> fromRow)
343+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
344+ FromField f, FromField g, FromField h, FromField i, FromField j,
345+ FromField k, FromField l, FromField m, FromField n, FromField o,
347+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) where
348+ fromRow = (,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
349+ <*> field <*> field <*> field <*> field <*> field
350+ <*> field <*> field <*> field <*> field <*> field
353+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
354+ FromField f, FromField g, FromField h, FromField i, FromField j,
355+ FromField k, FromField l, FromField m, FromField n, FromField o,
357+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)) where
358+ fromRow = (null *> null *> null *> null *> null *>
359+ null *> null *> null *> null *> null *>
360+ null *> null *> null *> null *> null *>
361+ null *> pure Nothing)
362+ <|> (Just <$> fromRow)
364+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
365+ FromField f, FromField g, FromField h, FromField i, FromField j,
366+ FromField k, FromField l, FromField m, FromField n, FromField o,
367+ FromField p, FromField q) =>
368+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q) where
369+ fromRow = (,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
370+ <*> field <*> field <*> field <*> field <*> field
371+ <*> field <*> field <*> field <*> field <*> field
374+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
375+ FromField f, FromField g, FromField h, FromField i, FromField j,
376+ FromField k, FromField l, FromField m, FromField n, FromField o,
377+ FromField p, FromField q) =>
378+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q)) where
379+ fromRow = (null *> null *> null *> null *> null *>
380+ null *> null *> null *> null *> null *>
381+ null *> null *> null *> null *> null *>
382+ null *> null *> pure Nothing)
383+ <|> (Just <$> fromRow)
385+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
386+ FromField f, FromField g, FromField h, FromField i, FromField j,
387+ FromField k, FromField l, FromField m, FromField n, FromField o,
388+ FromField p, FromField q, FromField r) =>
389+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) where
390+ fromRow = (,,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
391+ <*> field <*> field <*> field <*> field <*> field
392+ <*> field <*> field <*> field <*> field <*> field
393+ <*> field <*> field <*> field
395+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
396+ FromField f, FromField g, FromField h, FromField i, FromField j,
397+ FromField k, FromField l, FromField m, FromField n, FromField o,
398+ FromField p, FromField q, FromField r) =>
399+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)) where
400+ fromRow = (null *> null *> null *> null *> null *>
401+ null *> null *> null *> null *> null *>
402+ null *> null *> null *> null *> null *>
403+ null *> null *> null *> pure Nothing)
404+ <|> (Just <$> fromRow)
406+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
407+ FromField f, FromField g, FromField h, FromField i, FromField j,
408+ FromField k, FromField l, FromField m, FromField n, FromField o,
409+ FromField p, FromField q, FromField r, FromField s) =>
410+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s) where
411+ fromRow = (,,,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
412+ <*> field <*> field <*> field <*> field <*> field
413+ <*> field <*> field <*> field <*> field <*> field
414+ <*> field <*> field <*> field <*> field
416+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
417+ FromField f, FromField g, FromField h, FromField i, FromField j,
418+ FromField k, FromField l, FromField m, FromField n, FromField o,
419+ FromField p, FromField q, FromField r, FromField s) =>
420+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s)) where
421+ fromRow = (null *> null *> null *> null *> null *>
422+ null *> null *> null *> null *> null *>
423+ null *> null *> null *> null *> null *>
424+ null *> null *> null *> null *> pure Nothing)
425+ <|> (Just <$> fromRow)
427+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
428+ FromField f, FromField g, FromField h, FromField i, FromField j,
429+ FromField k, FromField l, FromField m, FromField n, FromField o,
430+ FromField p, FromField q, FromField r, FromField s, FromField t) =>
431+ FromRow (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t) where
432+ fromRow = (,,,,,,,,,,,,,,,,,,,) <$> field <*> field <*> field <*> field <*> field
433+ <*> field <*> field <*> field <*> field <*> field
434+ <*> field <*> field <*> field <*> field <*> field
435+ <*> field <*> field <*> field <*> field <*> field
437+instance (FromField a, FromField b, FromField c, FromField d, FromField e,
438+ FromField f, FromField g, FromField h, FromField i, FromField j,
439+ FromField k, FromField l, FromField m, FromField n, FromField o,
440+ FromField p, FromField q, FromField r, FromField s, FromField t) =>
441+ FromRow (Maybe (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t)) where
442+ fromRow = (null *> null *> null *> null *> null *>
443+ null *> null *> null *> null *> null *>
444+ null *> null *> null *> null *> null *>
445+ null *> null *> null *> null *> null *> pure Nothing)
446+ <|> (Just <$> fromRow)
169instance FromField a => FromRow [a] where
448instance FromField a => FromRow [a] where
170 fromRow = do
449 fromRow = do
171 n <- numFieldsRemaining
450 n <- numFieldsRemaining
172 replicateM n field
451 replicateM n field
453+instance FromField a => FromRow (Maybe [a]) where
455+ n <- numFieldsRemaining
456+ (replicateM_ n null *> pure Nothing) <|> (Just <$> replicateM n field)
458+instance FromField a => FromRow (Vector a) where
460+ n <- numFieldsRemaining
461+ V.replicateM n field
463+instance FromField a => FromRow (Maybe (Vector a)) where
465+ n <- numFieldsRemaining
466+ (replicateM_ n null *> pure Nothing) <|> (Just <$> V.replicateM n field)
174instance (FromRow a, FromRow b) => FromRow (a :. b) where
468instance (FromRow a, FromRow b) => FromRow (a :. b) where
175 fromRow = (:.) <$> fromRow <*> fromRow
469 fromRow = (:.) <$> fromRow <*> fromRow
473+-- Type class for default implementation of FromRow using generics
474+class GFromRow f where
475+ gfromRow :: RowParser (f p)
477+instance GFromRow f => GFromRow (M1 c i f) where
478+ gfromRow = M1 <$> gfromRow
480+instance (GFromRow f, GFromRow g) => GFromRow (f :*: g) where
481+ gfromRow = liftA2 (:*:) gfromRow gfromRow
483+instance (FromField a) => GFromRow (K1 R a) where
484+ gfromRow = K1 <$> field
486+instance GFromRow U1 where