@@ -3,12 +3,15 @@ module Database.Postgres
3
3
, Client ()
4
4
, DB ()
5
5
, ConnectionInfo ()
6
+ , SqlValue ()
7
+ , IsSqlValue
8
+ , toSql
6
9
, connect
7
10
, end
8
- , execute
9
- , query
10
- , queryOne
11
- , queryValue
11
+ , execute , execute_
12
+ , query , query_
13
+ , queryValue , queryValue_
14
+ , queryOne , queryOne_
12
15
, withConnection
13
16
) where
14
17
@@ -20,6 +23,7 @@ import Data.Array
20
23
import Data.Foreign
21
24
import Data.Foreign.Class
22
25
import Data.Maybe
26
+ import Data.Int
23
27
import Control.Monad.Aff
24
28
import Control.Monad.Eff.Class
25
29
import Control.Monad.Eff.Exception (Error (), error )
@@ -51,25 +55,53 @@ connect ci = connect'
51
55
<> ci.db
52
56
53
57
-- | Runs a query and returns nothing.
54
- execute :: forall eff a . Query a -> Client -> Aff (db :: DB | eff ) Unit
55
- execute (Query sql) client = void $ runQuery sql client
58
+ execute :: forall eff a . Query a -> [SqlValue ] -> Client -> Aff (db :: DB | eff ) Unit
59
+ execute (Query sql) params client = void $ runQuery sql params client
60
+
61
+ -- | Runs a query and returns nothing
62
+ execute_ :: forall eff a . Query a -> Client -> Aff (db :: DB | eff ) Unit
63
+ execute_ (Query sql) client = void $ runQuery_ sql client
56
64
57
65
-- | Runs a query and returns all results.
58
- query :: forall eff a . (IsForeign a ) => Query a -> Client -> Aff (db :: DB | eff ) [a ]
59
- query (Query sql) client = do
60
- rows <- runQuery sql client
66
+ query :: forall eff a p
67
+ . (IsForeign a )
68
+ => Query a -> [SqlValue ] -> Client -> Aff (db :: DB | eff ) [F a ]
69
+ query (Query sql) params client = do
70
+ rows <- runQuery sql params client
71
+ pure $ read <$> rows
72
+
73
+ -- | Just like `query` but does not make any param replacement
74
+ query_ :: forall eff a . (IsForeign a ) => Query a -> Client -> Aff (db :: DB | eff ) [a ]
75
+ query_ (Query sql) client = do
76
+ rows <- runQuery_ sql client
61
77
either liftError pure (sequence $ read <$> rows)
62
78
63
79
-- | Runs a query and returns the first row, if any
64
- queryOne :: forall eff a . (IsForeign a ) => Query a -> Client -> Aff (db :: DB | eff ) (Maybe a )
65
- queryOne (Query sql) client = do
66
- rows <- runQuery sql client
80
+ queryOne :: forall eff a
81
+ . (IsForeign a )
82
+ => Query a -> [SqlValue ] -> Client -> Aff (db :: DB | eff ) (Maybe a )
83
+ queryOne (Query sql) params client = do
84
+ rows <- runQuery sql params client
85
+ maybe (pure Nothing ) (either liftError (pure <<< Just )) $ read <$> (rows !! 0 )
86
+
87
+ -- | Just like `queryOne` but does not make any param replacement
88
+ queryOne_ :: forall eff a . (IsForeign a ) => Query a -> Client -> Aff (db :: DB | eff ) (Maybe a )
89
+ queryOne_ (Query sql) client = do
90
+ rows <- runQuery_ sql client
67
91
maybe (pure Nothing ) (either liftError (pure <<< Just )) $ read <$> (rows !! 0 )
68
92
69
93
-- | Runs a query and returns a single value, if any.
70
- queryValue :: forall eff a . (IsForeign a ) => Query a -> Client -> Aff (db :: DB | eff ) (Maybe a )
71
- queryValue (Query sql) client = do
72
- val <- runQueryValue sql client
94
+ queryValue :: forall eff a
95
+ . (IsForeign a )
96
+ => Query a -> [SqlValue ] -> Client -> Aff (db :: DB | eff ) (Maybe a )
97
+ queryValue (Query sql) params client = do
98
+ val <- runQueryValue sql params client
99
+ pure $ either (const Nothing ) Just (read val)
100
+
101
+ -- | Just like `queryValue` but does not make any param replacement
102
+ queryValue_ :: forall eff a . (IsForeign a ) => Query a -> Client -> Aff (db :: DB | eff ) (Maybe a )
103
+ queryValue_ (Query sql) client = do
104
+ val <- runQueryValue_ sql client
73
105
either liftError (pure <<< Just ) $ read val
74
106
75
107
-- | Connects to the database, calls the provided function with the client
@@ -91,6 +123,27 @@ finally a sequel = do
91
123
sequel
92
124
either throwError pure res
93
125
126
+ foreign import data SqlValue :: *
127
+
128
+ foreign import unsafeToSqlValue " " "
129
+ function unsafeToSqlValue(x) {
130
+ return x;
131
+ }
132
+ " " " :: forall a . a -> SqlValue
133
+
134
+ class IsSqlValue a where
135
+ toSql :: a -> SqlValue
136
+
137
+ instance isSqlValueString :: IsSqlValue String where
138
+ toSql = unsafeToSqlValue
139
+
140
+ instance isSqlValueNumber :: IsSqlValue Number where
141
+ toSql = unsafeToSqlValue
142
+
143
+ instance isSqlValueInt :: IsSqlValue Int where
144
+ toSql = unsafeToSqlValue <<< toNumber
145
+
146
+
94
147
foreign import connect' " " "
95
148
function connect$prime(conString) {
96
149
return function(success, error) {
@@ -108,8 +161,8 @@ foreign import connect' """
108
161
}
109
162
" " " :: forall eff . String -> Aff (db :: DB | eff ) Client
110
163
111
- foreign import runQuery " " "
112
- function runQuery (queryStr) {
164
+ foreign import runQuery_ " " "
165
+ function runQuery_ (queryStr) {
113
166
return function(client) {
114
167
return function(success, error) {
115
168
client.query(queryStr, function(err, result) {
@@ -124,8 +177,23 @@ foreign import runQuery """
124
177
}
125
178
" " " :: forall eff . String -> Client -> Aff (db :: DB | eff ) [Foreign ]
126
179
127
- foreign import runQueryValue " " "
128
- function runQueryValue(queryStr) {
180
+ foreign import runQuery " " "
181
+ function runQuery(queryStr) {
182
+ return function(params) {
183
+ return function(client) {
184
+ return function(success, error) {
185
+ client.query(queryStr, params, function(err, result) {
186
+ if (err) return error(err);
187
+ success(result.rows);
188
+ })
189
+ };
190
+ };
191
+ }
192
+ }
193
+ " " " :: forall eff . String -> [SqlValue ] -> Client -> Aff (db :: DB | eff ) [Foreign ]
194
+
195
+ foreign import runQueryValue_ " " "
196
+ function runQueryValue_(queryStr) {
129
197
return function(client) {
130
198
return function(success, error) {
131
199
client.query(queryStr, function(err, result) {
@@ -137,6 +205,21 @@ foreign import runQueryValue """
137
205
}
138
206
" " " :: forall eff . String -> Client -> Aff (db :: DB | eff ) Foreign
139
207
208
+ foreign import runQueryValue " " "
209
+ function runQueryValue(queryStr) {
210
+ return function(params) {
211
+ return function(client) {
212
+ return function(success, error) {
213
+ client.query(queryStr, params, function(err, result) {
214
+ if (err) return error(err);
215
+ success(result.rows.length > 0 ? result.rows[0][result.fields[0].name] : undefined);
216
+ })
217
+ };
218
+ };
219
+ }
220
+ }
221
+ " " " :: forall eff . String -> [SqlValue ] -> Client -> Aff (db :: DB | eff ) Foreign
222
+
140
223
foreign import end " " "
141
224
function end(client) {
142
225
return function() {
0 commit comments