git.iko.soy/typeable/postgresql-simple
on master help sign in
Rename Param and QueryParams, Move Field into FromField
commit9014819ce50c797c9f2cafa2a4258fe42d794702 authorLeon P Smith <leon@melding-monads.com> dateFri 4 May 2012, 12:45 (14 years ago) parent194683a
8 files changed+347−342
postgresql-simple.cabal+4−5 src/Database/PostgreSQL/Simple.hs+12−12 src/Database/PostgreSQL/Simple/Field.hs−15 src/Database/PostgreSQL/Simple/FromField.hs+33−20 src/Database/PostgreSQL/Simple/Param.hs−205 src/Database/PostgreSQL/Simple/QueryParams.hs−85 src/Database/PostgreSQL/Simple/ToField.hs+208 src/Database/PostgreSQL/Simple/ToRow.hs+90
postgresql-simple.cabal+4−5
@@ -1,5 +1,5 @@
11Name: postgresql-simple
2−Version: 0.0.99
2+Version: 0.1
33Synopsis: Mid-Level PostgreSQL client library
44Description:
55 Mid-Level PostgreSQL client library, forked from mysql-simple.
@@ -19,15 +19,14 @@ Library
1919 Exposed-modules:
2020 Database.PostgreSQL.Simple
2121 Database.PostgreSQL.Simple.BuiltinTypes
22− Database.PostgreSQL.Simple.Field
2322 Database.PostgreSQL.Simple.FromField
2423 Database.PostgreSQL.Simple.FromRow
2524 Database.PostgreSQL.Simple.LargeObjects
2625 Database.PostgreSQL.Simple.Notification
2726 Database.PostgreSQL.Simple.Ok
28− Database.PostgreSQL.Simple.Param
29− Database.PostgreSQL.Simple.QueryParams
3027 Database.PostgreSQL.Simple.SqlQQ
28+ Database.PostgreSQL.Simple.ToField
29+ Database.PostgreSQL.Simple.ToRow
3130 Database.PostgreSQL.Simple.Types
3231-- Other-modules:
3332 Database.PostgreSQL.Simple.Internal
@@ -63,4 +62,4 @@ source-repository head
6362source-repository this
6463 type: git
6564 location: http://github.com/lpsmith/postgresql-simple
66− tag: v0.0.5
65+ tag: v0.1
src/Database/PostgreSQL/Simple.hs+12−12
@@ -125,8 +125,8 @@ import Database.PostgreSQL.Simple.Compat ( mask )
125125import Database.PostgreSQL.Simple.FromField (ResultError(..))
126126import Database.PostgreSQL.Simple.FromRow (FromRow(..))
127127import Database.PostgreSQL.Simple.Ok
128−import Database.PostgreSQL.Simple.Param (Action(..), inQuotes)
129−import Database.PostgreSQL.Simple.QueryParams (QueryParams(..))
128+import Database.PostgreSQL.Simple.ToField (Action(..), inQuotes)
129+import Database.PostgreSQL.Simple.ToRow (ToRow(..))
130130import Database.PostgreSQL.Simple.Types
131131 ( Binary(..), In(..), Only(..), Query(..) )
132132import Database.PostgreSQL.Simple.Internal as Base
@@ -167,11 +167,11 @@ instance Exception QueryError
167167--
168168-- Throws 'FormatError' if the query string could not be formatted
169169-- correctly.
170−formatQuery :: QueryParams q => Connection -> Query -> q -> IO ByteString
170+formatQuery :: ToRow q => Connection -> Query -> q -> IO ByteString
171171formatQuery conn q@(Query template) qs
172172 | null xs && '?' `B.notElem` template = return template
173173 | otherwise = toByteString <$> buildQuery conn q template xs
174− where xs = renderParams qs
174+ where xs = toRow qs
175175
176176-- | Format a query string with a variable number of rows.
177177--
@@ -186,12 +186,12 @@ formatQuery conn q@(Query template) qs
186186--
187187-- Throws 'FormatError' if the query string could not be formatted
188188-- correctly.
189−formatMany :: (QueryParams q) => Connection -> Query -> [q] -> IO ByteString
189+formatMany :: (ToRow q) => Connection -> Query -> [q] -> IO ByteString
190190formatMany _ q [] = fmtError "no rows supplied" q []
191191formatMany conn q@(Query template) qs = do
192192 case match re template [] of
193193 Just [_,before,qbits,after] -> do
194− bs <- mapM (buildQuery conn q qbits . renderParams) qs
194+ bs <- mapM (buildQuery conn q qbits . toRow) qs
195195 return . toByteString . mconcat $ fromByteString before :
196196 intersperse (fromChar ',') bs ++
197197 [fromByteString after]
@@ -226,7 +226,7 @@ buildQuery conn q template xs = zipParams (split template) <$> mapM sub xs
226226-- Returns the number of rows affected.
227227--
228228-- Throws 'FormatError' if the query could not be formatted correctly.
229−execute :: (QueryParams q) => Connection -> Query -> q -> IO Int64
229+execute :: (ToRow q) => Connection -> Query -> q -> IO Int64
230230execute conn template qs = do
231231 result <- exec conn =<< formatQuery conn template qs
232232 finishExecute conn template result
@@ -243,7 +243,7 @@ execute_ conn q@(Query stmt) = do
243243-- Returns the number of rows affected.
244244--
245245-- Throws 'FormatError' if the query could not be formatted correctly.
246−executeMany :: (QueryParams q) => Connection -> Query -> [q] -> IO Int64
246+executeMany :: (ToRow q) => Connection -> Query -> [q] -> IO Int64
247247executeMany _ _ [] = return 0
248248executeMany conn q qs = do
249249 result <- exec conn =<< formatMany conn q qs
@@ -302,7 +302,7 @@ finishExecute _conn q result = do
302302-- using 'execute' instead of 'query').
303303--
304304-- * 'ResultError': result conversion failed.
305−query :: (QueryParams q, FromRow r)
305+query :: (ToRow q, FromRow r)
306306 => Connection -> Query -> q -> IO [r]
307307query conn template qs = do
308308 result <- exec conn =<< formatQuery conn template qs
@@ -333,7 +333,7 @@ query_ conn q@(Query que) = do
333333--
334334-- * 'ResultError': result conversion failed.
335335
336−fold :: ( FromRow row, QueryParams params )
336+fold :: ( FromRow row, ToRow params )
337337 => Connection
338338 -> Query
339339 -> params
@@ -358,7 +358,7 @@ defaultFoldOptions = FoldOptions {
358358 transactionMode = TransactionMode ReadCommitted ReadOnly
359359 }
360360
361−foldWithOptions :: ( FromRow row, QueryParams params )
361+foldWithOptions :: ( FromRow row, ToRow params )
362362 => FoldOptions
363363 -> Connection
364364 -> Query
@@ -436,7 +436,7 @@ doFold FoldOptions{..} conn _template q a f = do
436436 if null rs then return a else foldM f a rs >>= loop
437437
438438-- | A version of 'fold' that does not transform a state value.
439−forEach :: (QueryParams q, FromRow r) =>
439+forEach :: (ToRow q, FromRow r) =>
440440 Connection
441441 -> Query -- ^ Query template.
442442 -> q -- ^ Query parameters.
src/Database/PostgreSQL/Simple/Field.hsdeleted−15
@@ -1,15 +0,0 @@
1−module Database.PostgreSQL.Simple.Field
2− ( Field
3− , typename
4− , name
5− , tableOid
6− , tableColumn
7− , format
8− , typeOid
9− , Oid
10− , Format(..)
11− , RawResult(..)
12− ) where
13−
14−import Database.PostgreSQL.Simple.Internal
15−import Database.PostgreSQL.LibPQ (Format(..), Oid)
src/Database/PostgreSQL/Simple/FromField.hs+33−20
@@ -27,32 +27,45 @@ module Database.PostgreSQL.Simple.FromField
2727 FromField(..)
2828 , ResultError(..)
2929 , returnError
30+
31+ , Field
32+ , typename
33+ , name
34+ , tableOid
35+ , tableColumn
36+ , format
37+ , typeOid
38+ , PQ.Oid(..)
39+ , PQ.Format(..)
3040 ) where
3141
3242#include "MachDeps.h"
3343
34−import Control.Applicative (Applicative, (<|>), (<$>), (<*>), (<*), pure)
35−import Control.Exception (SomeException(..), Exception)
36−import Data.Attoparsec.Char8 hiding (Result)
37−import Data.Bits ((.&.), (.|.), shiftL)
38−import Data.ByteString (ByteString)
44+import Control.Applicative
45+ ( Applicative, (<|>), (<$>), (<*>), (<*), pure )
46+import Control.Exception (SomeException(..), Exception)
47+import Data.Attoparsec.Char8 hiding (Result)
48+import Data.Bits ((.&.), (.|.), shiftL)
49+import Data.ByteString (ByteString)
3950import qualified Data.ByteString.Char8 as B
40−import Data.Int (Int16, Int32, Int64)
41−import Data.List (foldl')
42−import Data.Ratio (Ratio)
43−import Data.Time.Calendar (Day, fromGregorian)
44−import Data.Time.Clock (UTCTime)
45−import Data.Time.Format (parseTime)
46−import Data.Time.LocalTime (TimeOfDay, makeTimeOfDayValid)
47−import Data.Typeable (Typeable, typeOf)
48−import Data.Word (Word64)
49−import Database.PostgreSQL.Simple.Internal
50−import Database.PostgreSQL.Simple.BuiltinTypes
51−import Database.PostgreSQL.Simple.Ok
52−import Database.PostgreSQL.Simple.Types (Binary(..), Null(..))
51+import Data.Int (Int16, Int32, Int64)
52+import Data.List (foldl')
53+import Data.Ratio (Ratio)
54+import Data.Time.Calendar (Day, fromGregorian)
55+import Data.Time.Clock (UTCTime)
56+import Data.Time.Format (parseTime)
57+import Data.Time.LocalTime (TimeOfDay, makeTimeOfDayValid)
58+import Data.Typeable (Typeable, typeOf)
59+import Data.Word (Word64)
60+import Database.PostgreSQL.Simple.Internal
61+import Database.PostgreSQL.Simple.BuiltinTypes
62+-- import qualified Database.PostgreSQ
63+import Database.PostgreSQL.Simple.Ok
64+import Database.PostgreSQL.Simple.Types (Binary(..), Null(..))
5365import qualified Database.PostgreSQL.LibPQ as PQ
54−import System.IO.Unsafe (unsafePerformIO)
55−import System.Locale (defaultTimeLocale)
66+-- import Database.PostgreSQL.LibPQ (Format(..), Oid(..))
67+import System.IO.Unsafe (unsafePerformIO)
68+import System.Locale (defaultTimeLocale)
5669import qualified Data.ByteString as SB
5770import qualified Data.ByteString.Char8 as B8
5871import qualified Data.ByteString.Lazy as LB
src/Database/PostgreSQL/Simple/Param.hsdeleted−205
@@ -1,205 +0,0 @@
1−{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, FlexibleInstances #-}
2−
3−-- |
4−-- Module: Database.PostgreSQL.Simple.Param
5−-- Copyright: (c) 2011 MailRank, Inc.
6−-- (c) 2011 Leon P Smith
7−-- License: BSD3
8−-- Maintainer: Leon P Smith <leon@melding-monads.com>
9−-- Stability: experimental
10−-- Portability: portable
11−--
12−-- The 'Param' typeclass, for rendering a parameter to a SQL query.
13−
14−module Database.PostgreSQL.Simple.Param
15− (
16− Action(..)
17− , Param(..)
18− , inQuotes
19− ) where
20−
21−import Blaze.ByteString.Builder (Builder, fromByteString, fromLazyByteString,
22− toByteString)
23−import Blaze.ByteString.Builder.Char8 (fromChar)
24−import Blaze.Text (integral, double, float)
25−import Data.ByteString (ByteString)
26−import qualified Data.ByteString.Base16 as B16
27−import qualified Data.ByteString.Base16.Lazy as L16
28−import Data.Int (Int8, Int16, Int32, Int64)
29−import Data.List (intersperse)
30−import Data.Monoid (mappend)
31−import Data.Time.Calendar (Day, showGregorian)
32−import Data.Time.Clock (UTCTime)
33−import Data.Time.Format (formatTime)
34−import Data.Time.LocalTime (TimeOfDay)
35−import Data.Typeable (Typeable)
36−import Data.Word (Word, Word8, Word16, Word32, Word64)
37−import Database.PostgreSQL.Simple.Types (Binary(..), In(..), Null)
38−import System.Locale (defaultTimeLocale)
39−import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8
40−import qualified Data.ByteString as SB
41−import qualified Data.ByteString.Lazy as LB
42−import qualified Data.Text as ST
43−import qualified Data.Text.Encoding as ST
44−import qualified Data.Text.Lazy as LT
45−import qualified Database.PostgreSQL.LibPQ as PQ
46−
47−-- | How to render an element when substituting it into a query.
48−data Action =
49− Plain Builder
50− -- ^ Render without escaping or quoting. Use for non-text types
51− -- such as numbers, when you are /certain/ that they will not
52− -- introduce formatting vulnerabilities via use of characters such
53− -- as spaces or \"@'@\".
54− | Escape ByteString
55− -- ^ Escape and enclose in quotes before substituting. Use for all
56− -- text-like types, and anything else that may contain unsafe
57− -- characters when rendered.
58− | Many [Action]
59− -- ^ Concatenate a series of rendering actions.
60− deriving (Typeable)
61−
62−instance Show Action where
63− show (Plain b) = "Plain " ++ show (toByteString b)
64− show (Escape b) = "Escape " ++ show b
65− show (Many b) = "Many " ++ show b
66−
67−-- | A type that may be used as a single parameter to a SQL query.
68−class Param a where
69− render :: a -> Action
70− -- ^ Prepare a value for substitution into a query string.
71−
72−instance Param Action where
73− render a = a
74− {-# INLINE render #-}
75−
76−instance (Param a) => Param (Maybe a) where
77− render Nothing = renderNull
78− render (Just a) = render a
79− {-# INLINE render #-}
80−
81−instance (Param a) => Param (In [a]) where
82− render (In []) = Plain $ fromByteString "(null)"
83− render (In xs) = Many $
84− Plain (fromChar '(') :
85− (intersperse (Plain (fromChar ',')) . map render $ xs) ++
86− [Plain (fromChar ')')]
87−
88−instance Param (Binary SB.ByteString) where
89− render (Binary bs) = Plain $ fromByteString "'\\x" `mappend`
90− fromByteString (B16.encode bs) `mappend`
91− fromChar '\''
92−
93−instance Param (Binary LB.ByteString) where
94− render (Binary bs) = Plain $ fromByteString "'\\x" `mappend`
95− fromLazyByteString (L16.encode bs) `mappend`
96− fromChar '\''
97−
98−renderNull :: Action
99−renderNull = Plain (fromByteString "null")
100−
101−instance Param Null where
102− render _ = renderNull
103− {-# INLINE render #-}
104−
105−instance Param Bool where
106− render True = Plain (fromByteString "true")
107− render False = Plain (fromByteString "false")
108− {-# INLINE render #-}
109−
110−instance Param Int8 where
111− render = Plain . integral
112− {-# INLINE render #-}
113−
114−instance Param Int16 where
115− render = Plain . integral
116− {-# INLINE render #-}
117−
118−instance Param Int32 where
119− render = Plain . integral
120− {-# INLINE render #-}
121−
122−instance Param Int where
123− render = Plain . integral
124− {-# INLINE render #-}
125−
126−instance Param Int64 where
127− render = Plain . integral
128− {-# INLINE render #-}
129−
130−instance Param Integer where
131− render = Plain . integral
132− {-# INLINE render #-}
133−
134−instance Param Word8 where
135− render = Plain . integral
136− {-# INLINE render #-}
137−
138−instance Param Word16 where
139− render = Plain . integral
140− {-# INLINE render #-}
141−
142−instance Param Word32 where
143− render = Plain . integral
144− {-# INLINE render #-}
145−
146−instance Param Word where
147− render = Plain . integral
148− {-# INLINE render #-}
149−
150−instance Param Word64 where
151− render = Plain . integral
152− {-# INLINE render #-}
153−
154−instance Param PQ.Oid where
155− render = Plain . integral . \(PQ.Oid x) -> x
156− {-# INLINE render #-}
157−
158−instance Param Float where
159− render v | isNaN v || isInfinite v = Plain (inQuotes (float v))
160− | otherwise = Plain (float v)
161− {-# INLINE render #-}
162−
163−instance Param Double where
164− render v | isNaN v || isInfinite v = Plain (inQuotes (double v))
165− | otherwise = Plain (double v)
166− {-# INLINE render #-}
167−
168−instance Param SB.ByteString where
169− render = Escape
170− {-# INLINE render #-}
171−
172−instance Param LB.ByteString where
173− render = render . SB.concat . LB.toChunks
174− {-# INLINE render #-}
175−
176−instance Param ST.Text where
177− render = Escape . ST.encodeUtf8
178− {-# INLINE render #-}
179−
180−instance Param [Char] where
181− render = Escape . toByteString . Utf8.fromString
182− {-# INLINE render #-}
183−
184−instance Param LT.Text where
185− render = render . LT.toStrict
186− {-# INLINE render #-}
187−
188−instance Param UTCTime where
189− render = Plain . Utf8.fromString . formatTime defaultTimeLocale "'%F %T%Q+00'"
190− {-# INLINE render #-}
191−
192−instance Param Day where
193− render = Plain . inQuotes . Utf8.fromString . showGregorian
194− {-# INLINE render #-}
195−
196−instance Param TimeOfDay where
197− render = Plain . inQuotes . Utf8.fromString . show
198− {-# INLINE render #-}
199−
200−-- | Surround a string with single-quote characters: \"@'@\"
201−--
202−-- This function /does not/ perform any other escaping.
203−inQuotes :: Builder -> Builder
204−inQuotes b = quote `mappend` b `mappend` quote
205− where quote = Utf8.fromChar '\''
src/Database/PostgreSQL/Simple/QueryParams.hsdeleted−85
@@ -1,85 +0,0 @@
1−-- |
2−-- Module: Database.PostgreSQL.Simple.QueryParams
3−-- Copyright: (c) 2011 MailRank, Inc.
4−-- (c) 2011 Leon P Smith
5−-- License: BSD3
6−-- Maintainer: Leon P Smith <leon@melding-monads.com>
7−-- Stability: experimental
8−-- Portability: portable
9−--
10−-- The 'QueryParams' typeclass, for rendering a collection of
11−-- parameters to a SQL query.
12−--
13−-- Predefined instances are provided for tuples containing up to ten
14−-- elements.
15−
16−module Database.PostgreSQL.Simple.QueryParams
17− (
18− QueryParams(..)
19− ) where
20−
21−import Database.PostgreSQL.Simple.Param (Action(..), Param(..))
22−import Database.PostgreSQL.Simple.Types (Only(..))
23−
24−-- | A collection type that can be turned into a list of rendering
25−-- 'Action's.
26−--
27−-- Instances should use the 'render' method of the 'Param' class
28−-- to perform conversion of each element of the collection.
29−class QueryParams a where
30− renderParams :: a -> [Action]
31− -- ^ Render a collection of values.
32−
33−instance QueryParams () where
34− renderParams _ = []
35−
36−instance (Param a) => QueryParams (Only a) where
37− renderParams (Only v) = [render v]
38−
39−instance (Param a, Param b) => QueryParams (a,b) where
40− renderParams (a,b) = [render a, render b]
41−
42−instance (Param a, Param b, Param c) => QueryParams (a,b,c) where
43− renderParams (a,b,c) = [render a, render b, render c]
44−
45−instance (Param a, Param b, Param c, Param d) => QueryParams (a,b,c,d) where
46− renderParams (a,b,c,d) = [render a, render b, render c, render d]
47−
48−instance (Param a, Param b, Param c, Param d, Param e)
49− => QueryParams (a,b,c,d,e) where
50− renderParams (a,b,c,d,e) =
51− [render a, render b, render c, render d, render e]
52−
53−instance (Param a, Param b, Param c, Param d, Param e, Param f)
54− => QueryParams (a,b,c,d,e,f) where
55− renderParams (a,b,c,d,e,f) =
56− [render a, render b, render c, render d, render e, render f]
57−
58−instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g)
59− => QueryParams (a,b,c,d,e,f,g) where
60− renderParams (a,b,c,d,e,f,g) =
61− [render a, render b, render c, render d, render e, render f, render g]
62−
63−instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g,
64− Param h)
65− => QueryParams (a,b,c,d,e,f,g,h) where
66− renderParams (a,b,c,d,e,f,g,h) =
67− [render a, render b, render c, render d, render e, render f, render g,
68− render h]
69−
70−instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g,
71− Param h, Param i)
72− => QueryParams (a,b,c,d,e,f,g,h,i) where
73− renderParams (a,b,c,d,e,f,g,h,i) =
74− [render a, render b, render c, render d, render e, render f, render g,
75− render h, render i]
76−
77−instance (Param a, Param b, Param c, Param d, Param e, Param f, Param g,
78− Param h, Param i, Param j)
79− => QueryParams (a,b,c,d,e,f,g,h,i,j) where
80− renderParams (a,b,c,d,e,f,g,h,i,j) =
81− [render a, render b, render c, render d, render e, render f, render g,
82− render h, render i, render j]
83−
84−instance (Param a) => QueryParams [a] where
85− renderParams = map render
src/Database/PostgreSQL/Simple/ToField.hsnew file+208
@@ -0,0 +1,208 @@
1+{-# LANGUAGE DeriveDataTypeable, DeriveFunctor, FlexibleInstances #-}
2+
3+------------------------------------------------------------------------------
4+-- |
5+-- Module: Database.PostgreSQL.Simple.ToField
6+-- Copyright: (c) 2011 MailRank, Inc.
7+-- (c) 2011 Leon P Smith
8+-- License: BSD3
9+-- Maintainer: Leon P Smith <leon@melding-monads.com>
10+-- Stability: experimental
11+-- Portability: portable
12+--
13+-- The 'ToField' typeclass, for rendering a parameter to a SQL query.
14+--
15+------------------------------------------------------------------------------
16+
17+module Database.PostgreSQL.Simple.ToField
18+ (
19+ Action(..)
20+ , ToField(..)
21+ , inQuotes
22+ ) where
23+
24+import Blaze.ByteString.Builder (Builder, fromByteString, fromLazyByteString,
25+ toByteString)
26+import Blaze.ByteString.Builder.Char8 (fromChar)
27+import Blaze.Text (integral, double, float)
28+import Data.ByteString (ByteString)
29+import qualified Data.ByteString.Base16 as B16
30+import qualified Data.ByteString.Base16.Lazy as L16
31+import Data.Int (Int8, Int16, Int32, Int64)
32+import Data.List (intersperse)
33+import Data.Monoid (mappend)
34+import Data.Time.Calendar (Day, showGregorian)
35+import Data.Time.Clock (UTCTime)
36+import Data.Time.Format (formatTime)
37+import Data.Time.LocalTime (TimeOfDay)
38+import Data.Typeable (Typeable)
39+import Data.Word (Word, Word8, Word16, Word32, Word64)
40+import Database.PostgreSQL.Simple.Types (Binary(..), In(..), Null)
41+import System.Locale (defaultTimeLocale)
42+import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8
43+import qualified Data.ByteString as SB
44+import qualified Data.ByteString.Lazy as LB
45+import qualified Data.Text as ST
46+import qualified Data.Text.Encoding as ST
47+import qualified Data.Text.Lazy as LT
48+import qualified Database.PostgreSQL.LibPQ as PQ
49+
50+-- | How to render an element when substituting it into a query.
51+data Action =
52+ Plain Builder
53+ -- ^ Render without escaping or quoting. Use for non-text types
54+ -- such as numbers, when you are /certain/ that they will not
55+ -- introduce formatting vulnerabilities via use of characters such
56+ -- as spaces or \"@'@\".
57+ | Escape ByteString
58+ -- ^ Escape and enclose in quotes before substituting. Use for all
59+ -- text-like types, and anything else that may contain unsafe
60+ -- characters when rendered.
61+ | Many [Action]
62+ -- ^ Concatenate a series of rendering actions.
63+ deriving (Typeable)
64+
65+instance Show Action where
66+ show (Plain b) = "Plain " ++ show (toByteString b)
67+ show (Escape b) = "Escape " ++ show b
68+ show (Many b) = "Many " ++ show b
69+
70+-- | A type that may be used as a single parameter to a SQL query.
71+class ToField a where
72+ toField :: a -> Action
73+ -- ^ Prepare a value for substitution into a query string.
74+
75+instance ToField Action where
76+ toField a = a
77+ {-# INLINE toField #-}
78+
79+instance (ToField a) => ToField (Maybe a) where
80+ toField Nothing = renderNull
81+ toField (Just a) = toField a
82+ {-# INLINE toField #-}
83+
84+instance (ToField a) => ToField (In [a]) where
85+ toField (In []) = Plain $ fromByteString "(null)"
86+ toField (In xs) = Many $
87+ Plain (fromChar '(') :
88+ (intersperse (Plain (fromChar ',')) . map toField $ xs) ++
89+ [Plain (fromChar ')')]
90+
91+instance ToField (Binary SB.ByteString) where
92+ toField (Binary bs) = Plain $ fromByteString "'\\x" `mappend`
93+ fromByteString (B16.encode bs) `mappend`
94+ fromChar '\''
95+
96+instance ToField (Binary LB.ByteString) where
97+ toField (Binary bs) = Plain $ fromByteString "'\\x" `mappend`
98+ fromLazyByteString (L16.encode bs) `mappend`
99+ fromChar '\''
100+
101+renderNull :: Action
102+renderNull = Plain (fromByteString "null")
103+
104+instance ToField Null where
105+ toField _ = renderNull
106+ {-# INLINE toField #-}
107+
108+instance ToField Bool where
109+ toField True = Plain (fromByteString "true")
110+ toField False = Plain (fromByteString "false")
111+ {-# INLINE toField #-}
112+
113+instance ToField Int8 where
114+ toField = Plain . integral
115+ {-# INLINE toField #-}
116+
117+instance ToField Int16 where
118+ toField = Plain . integral
119+ {-# INLINE toField #-}
120+
121+instance ToField Int32 where
122+ toField = Plain . integral
123+ {-# INLINE toField #-}
124+
125+instance ToField Int where
126+ toField = Plain . integral
127+ {-# INLINE toField #-}
128+
129+instance ToField Int64 where
130+ toField = Plain . integral
131+ {-# INLINE toField #-}
132+
133+instance ToField Integer where
134+ toField = Plain . integral
135+ {-# INLINE toField #-}
136+
137+instance ToField Word8 where
138+ toField = Plain . integral
139+ {-# INLINE toField #-}
140+
141+instance ToField Word16 where
142+ toField = Plain . integral
143+ {-# INLINE toField #-}
144+
145+instance ToField Word32 where
146+ toField = Plain . integral
147+ {-# INLINE toField #-}
148+
149+instance ToField Word where
150+ toField = Plain . integral
151+ {-# INLINE toField #-}
152+
153+instance ToField Word64 where
154+ toField = Plain . integral
155+ {-# INLINE toField #-}
156+
157+instance ToField PQ.Oid where
158+ toField = Plain . integral . \(PQ.Oid x) -> x
159+ {-# INLINE toField #-}
160+
161+instance ToField Float where
162+ toField v | isNaN v || isInfinite v = Plain (inQuotes (float v))
163+ | otherwise = Plain (float v)
164+ {-# INLINE toField #-}
165+
166+instance ToField Double where
167+ toField v | isNaN v || isInfinite v = Plain (inQuotes (double v))
168+ | otherwise = Plain (double v)
169+ {-# INLINE toField #-}
170+
171+instance ToField SB.ByteString where
172+ toField = Escape
173+ {-# INLINE toField #-}
174+
175+instance ToField LB.ByteString where
176+ toField = toField . SB.concat . LB.toChunks
177+ {-# INLINE toField #-}
178+
179+instance ToField ST.Text where
180+ toField = Escape . ST.encodeUtf8
181+ {-# INLINE toField #-}
182+
183+instance ToField [Char] where
184+ toField = Escape . toByteString . Utf8.fromString
185+ {-# INLINE toField #-}
186+
187+instance ToField LT.Text where
188+ toField = toField . LT.toStrict
189+ {-# INLINE toField #-}
190+
191+instance ToField UTCTime where
192+ toField = Plain . Utf8.fromString . formatTime defaultTimeLocale "'%F %T%Q+00'"
193+ {-# INLINE toField #-}
194+
195+instance ToField Day where
196+ toField = Plain . inQuotes . Utf8.fromString . showGregorian
197+ {-# INLINE toField #-}
198+
199+instance ToField TimeOfDay where
200+ toField = Plain . inQuotes . Utf8.fromString . show
201+ {-# INLINE toField #-}
202+
203+-- | Surround a string with single-quote characters: \"@'@\"
204+--
205+-- This function /does not/ perform any other escaping.
206+inQuotes :: Builder -> Builder
207+inQuotes b = quote `mappend` b `mappend` quote
208+ where quote = Utf8.fromChar '\''
src/Database/PostgreSQL/Simple/ToRow.hsnew file+90
@@ -0,0 +1,90 @@
1+------------------------------------------------------------------------------
2+-- |
3+-- Module: Database.PostgreSQL.Simple.QueryParams
4+-- Copyright: (c) 2011 MailRank, Inc.
5+-- (c) 2011 Leon P Smith
6+-- License: BSD3
7+-- Maintainer: Leon P Smith <leon@melding-monads.com>
8+-- Stability: experimental
9+-- Portability: portable
10+--
11+-- The 'QueryParams' typeclass, for rendering a collection of
12+-- parameters to a SQL query.
13+--
14+-- Predefined instances are provided for tuples containing up to ten
15+-- elements.
16+--
17+------------------------------------------------------------------------------
18+
19+module Database.PostgreSQL.Simple.ToRow
20+ (
21+ ToRow(..)
22+ ) where
23+
24+import Database.PostgreSQL.Simple.ToField (Action(..), ToField(..))
25+import Database.PostgreSQL.Simple.Types (Only(..))
26+
27+-- | A collection type that can be turned into a list of rendering
28+-- 'Action's.
29+--
30+-- Instances should use the 'render' method of the 'Param' class
31+-- to perform conversion of each element of the collection.
32+class ToRow a where
33+ toRow :: a -> [Action]
34+ -- ^ ToField a collection of values.
35+
36+instance ToRow () where
37+ toRow _ = []
38+
39+instance (ToField a) => ToRow (Only a) where
40+ toRow (Only v) = [toField v]
41+
42+instance (ToField a, ToField b) => ToRow (a,b) where
43+ toRow (a,b) = [toField a, toField b]
44+
45+instance (ToField a, ToField b, ToField c) => ToRow (a,b,c) where
46+ toRow (a,b,c) = [toField a, toField b, toField c]
47+
48+instance (ToField a, ToField b, ToField c, ToField d) => ToRow (a,b,c,d) where
49+ toRow (a,b,c,d) = [toField a, toField b, toField c, toField d]
50+
51+instance (ToField a, ToField b, ToField c, ToField d, ToField e)
52+ => ToRow (a,b,c,d,e) where
53+ toRow (a,b,c,d,e) =
54+ [toField a, toField b, toField c, toField d, toField e]
55+
56+instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f)
57+ => ToRow (a,b,c,d,e,f) where
58+ toRow (a,b,c,d,e,f) =
59+ [toField a, toField b, toField c, toField d, toField e, toField f]
60+
61+instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
62+ ToField g)
63+ => ToRow (a,b,c,d,e,f,g) where
64+ toRow (a,b,c,d,e,f,g) =
65+ [toField a, toField b, toField c, toField d, toField e, toField f,
66+ toField g]
67+
68+instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
69+ ToField g, ToField h)
70+ => ToRow (a,b,c,d,e,f,g,h) where
71+ toRow (a,b,c,d,e,f,g,h) =
72+ [toField a, toField b, toField c, toField d, toField e, toField f,
73+ toField g, toField h]
74+
75+instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
76+ ToField g, ToField h, ToField i)
77+ => ToRow (a,b,c,d,e,f,g,h,i) where
78+ toRow (a,b,c,d,e,f,g,h,i) =
79+ [toField a, toField b, toField c, toField d, toField e, toField f,
80+ toField g, toField h, toField i]
81+
82+instance (ToField a, ToField b, ToField c, ToField d, ToField e, ToField f,
83+ ToField g, ToField h, ToField i, ToField j)
84+ => ToRow (a,b,c,d,e,f,g,h,i,j) where
85+ toRow (a,b,c,d,e,f,g,h,i,j) =
86+ [toField a, toField b, toField c, toField d, toField e, toField f,
87+ toField g, toField h, toField i, toField j]
88+
89+instance (ToField a) => ToRow [a] where
90+ toRow = map toField