on dev help sign in
query execution functions

implement * exec * execParams * prepare * execPrepared

commitec4c436a28c0b4ff1a3400e554575badbfea3e4a authorEitan Chatav <eitan.chatav@gmail.com> dateSun 19 Mar 2017, 01:07 (10 years ago) parent8424e0c
3 files changed+81−21
squeel-postgresql/src/Squeel/PostgreSQL/PQ.hs+49−16 squeel-postgresql/src/Squeel/PostgreSQL/Type.hs+14 squeel-postgresql/src/Squeel/PostgreSQL/Value.hs+18−5
squeel-postgresql/src/Squeel/PostgreSQL/PQ.hs+49−16
@@ -1,8 +1,11 @@
11{-# LANGUAGE
22 DataKinds
3+ , FlexibleContexts
34 , PolyKinds
5+ , RecordWildCards
46 , ScopedTypeVariables
57 , TypeApplications
8+ , TypeFamilies
69 , TypeOperators
710#-}
811
@@ -12,11 +15,14 @@ import Control.Monad.IO.Class
1215import Data.ByteString (ByteString)
1316import Data.Proxy
1417import Data.Text (Text)
18+import Data.Vinyl
19+import Data.Vinyl.Functor
1520
1621import qualified Database.PostgreSQL.LibPQ as LibPQ
1722
1823import Squeel.PostgreSQL.Query
1924import Squeel.PostgreSQL.Value
25+import Squeel.PostgreSQL.Type
2026
2127newtype Connection db = Connection { unConnection :: LibPQ.Connection }
2228
@@ -37,27 +43,54 @@ finish = liftIO . LibPQ.finish . unConnection
3743
3844newtype Result xs = Result { unResult :: LibPQ.Result }
3945
40−exec :: MonadIO io => Query db0 db1 '[] xs -> PQ io db0 db1 (Result xs)
41−exec = undefined
42−
43−type family To xs y where
44− To '[] y = y
45− To (x ': xs) y = To x (To xs y)
46+exec
47+ :: MonadIO io
48+ => Query db0 db1 '[] xs
49+ -> PQ io db0 db1 (Maybe (Result xs))
50+exec (Query q) = PQ $ \ (Connection conn) -> do
51+ result <- liftIO $ LibPQ.exec conn q
52+ return (Result <$> result, Connection conn)
4653
4754execParams
48− :: (MonadIO io, ToParameters xs ps)
49− => Connection db0
50− -> Query db0 db1 ps ys
51− -> xs `To` PQ io db0 db1 (Result ys)
52−execParams = undefined
55+ :: (MonadIO io, ToValues xs ps, ToOids ps)
56+ => Query db0 db1 ps ys
57+ -> Rec Identity xs
58+ -> PQ io db0 db1 (Maybe (Result ys))
59+execParams (Query q :: Query db0 db1 ps ys) params =
60+ PQ $ \ (Connection conn) -> do
61+ let
62+ params' =
63+ [ Just (oid, param, LibPQ.Binary)
64+ | (oid, param) <-
65+ zip (toOids (Proxy @ps)) (toValues (Proxy @ps) params)
66+ ]
67+ result <- liftIO $ LibPQ.execParams conn q params' LibPQ.Binary
68+ return (Result <$> result, Connection conn)
5369
5470prepare
55− :: MonadIO io
56− => Connection db0
57− -> ByteString
71+ :: (MonadIO io, ToOids ps)
72+ => ByteString
5873 -> Query db0 db1 ps xs
59− -> io (PreparedQuery db0 db1 ps xs)
60−prepare = undefined
74+ -> PQ io db0 db0 (Maybe (Result []), PreparedQuery db0 db1 ps xs)
75+prepare statementName (Query q :: Query db0 db1 ps ys) =
76+ PQ $ \ (Connection conn) -> do
77+ result <- liftIO $
78+ LibPQ.prepare conn statementName q (Just (toOids (Proxy @ps)))
79+ return ((Result <$> result,PreparedQuery statementName), Connection conn)
80+
81+execPrepared
82+ :: (MonadIO io, ToValues xs ps)
83+ => PreparedQuery db0 db1 ps ys
84+ -> Rec Identity xs
85+ -> PQ io db0 db1 (Maybe (Result ys))
86+execPrepared (PreparedQuery q :: PreparedQuery db0 db1 ps ys) params =
87+ PQ $ \ (Connection conn) -> do
88+ let
89+ params' =
90+ [Just (param, LibPQ.Binary) | param <- toValues (Proxy @ps) params]
91+ result <- liftIO $
92+ LibPQ.execPrepared conn q params' LibPQ.Binary
93+ return (Result <$> result, Connection conn)
6194
6295newtype RowNumber = RowNumber { unRowNumber :: LibPQ.Row }
6396
squeel-postgresql/src/Squeel/PostgreSQL/Type.hs+14
@@ -1,11 +1,16 @@
11{-# LANGUAGE
22 DataKinds
3+ , PolyKinds
4+ , ScopedTypeVariables
5+ , TypeApplications
36 , TypeFamilies
47 , TypeOperators
58#-}
69
710module Squeel.PostgreSQL.Type where
811
12+import Data.Proxy
13+import qualified Database.PostgreSQL.LibPQ as LibPQ
914import GHC.TypeLits
1015
1116newtype PGType = PGType Symbol
@@ -40,3 +45,12 @@ type family DatabaseTables database where
4045
4146type family SchemaDatabases schema where
4247 SchemaDatabases ('Schema schema databases) = databases
48+
49+class ToOid pg where
50+ toOid :: Proxy pg -> LibPQ.Oid
51+
52+class ToOids pgs where
53+ toOids :: Proxy pgs -> [LibPQ.Oid]
54+instance ToOids '[] where toOids _ = []
55+instance (ToOid pg, ToOids pgs) => ToOids (pg ': pgs) where
56+ toOids (_ :: Proxy (pg ': pgs)) = toOid (Proxy @pg) : toOids (Proxy @pgs)
squeel-postgresql/src/Squeel/PostgreSQL/Value.hs+18−5
@@ -1,8 +1,14 @@
11{-# LANGUAGE
22 DataKinds
33 , FlexibleInstances
4+ , FunctionalDependencies
45 , KindSignatures
56 , MultiParamTypeClasses
7+ , PolyKinds
8+ , ScopedTypeVariables
9+ , TypeApplications
10+ , TypeFamilies
11+ , TypeOperators
612#-}
713
814module Squeel.PostgreSQL.Value where
@@ -11,10 +17,13 @@ import Control.Arrow (left)
1117import Data.Aeson (FromJSON, ToJSON, eitherDecodeStrict, encode)
1218import Data.Bits (Bits)
1319import Data.ByteString (ByteString)
20+import Data.ByteString.Builder
1421import qualified Data.ByteString.Lazy as Lazy (ByteString, toStrict)
1522import Data.Int (Int16,Int32,Int64)
23+import Data.Proxy
24+import Data.Vinyl
25+import Data.Vinyl.Functor
1626import PostgreSQL.Binary.Decoder (Decoder)
17−import PostgreSQL.Binary.Encoder (Encoder)
1827import qualified PostgreSQL.Binary.Decoder as Decoder
1928import qualified PostgreSQL.Binary.Encoder as Encoder
2029import Data.Proxy (Proxy)
@@ -73,7 +82,7 @@ instance FromValue ('PGType "interval") DiffTime where
7382 fromValue _ = Decoder.interval_int
7483
7584class ToValue x (pg :: PGType) where
76− toValue :: Proxy pg -> Encoder x
85+ toValue :: Proxy pg -> x -> Builder
7786instance ToValue Int16 ('PGType "int2") where
7887 toValue _ = Encoder.int2_int16
7988instance ToValue Int32 ('PGType "int4") where
@@ -123,6 +132,10 @@ instance ToValue UTCTime ('PGType "timestamptz") where
123132instance ToValue DiffTime ('PGType "interval") where
124133 toValue _ = Encoder.interval_int
125134
126−type family ToParameters ps xs where
127− ToParameters '[] '[] = ()
128− ToParameters (x ': xs) (p ': ps) = (ToValue x p, ToParameters xs ps)
135+class ToValues xs pgs where
136+ toValues :: Proxy pgs -> Rec Identity xs -> [ByteString]
137+instance ToValues '[] '[] where toValues _ _ = []
138+instance (ToValue x pg, ToValues xs pgs)
139+ => ToValues (x ': xs) (pg ': pgs) where
140+ toValues (_ :: Proxy (pg ': pgs)) (Identity x :& xs) =
141+ Encoder.run (toValue (Proxy @pg)) x : toValues (Proxy @pgs) xs