diff --git a/src/Database/PostgreSQL.js b/src/Database/PostgreSQL.js index 3007fba..b120a39 100644 --- a/src/Database/PostgreSQL.js +++ b/src/Database/PostgreSQL.js @@ -51,3 +51,26 @@ exports.ffiUnsafeQuery = function(client) { }; }; }; + +exports.ffiUnsafeCommand = function(client) { + return function(sql) { + return function(values) { + return function(onError, onSuccess) { + var q = client.query({ + text: sql, + values: values, + rowMode: 'array', + }).catch(function(err) { + onError(err); + }).then(function(result) { + onSuccess(result.rowCount); + }); + + return function (cancelError, cancelerError, cancelerSuccess) { + q.cancel(); + cancelerSuccess(); + }; + }; + }; + }; +}; diff --git a/src/Database/PostgreSQL.purs b/src/Database/PostgreSQL.purs index 8d9736a..e7dbf4b 100644 --- a/src/Database/PostgreSQL.purs +++ b/src/Database/PostgreSQL.purs @@ -8,6 +8,7 @@ module Database.PostgreSQL , newPool , withConnection , withTransaction +, command , execute , query , scalar @@ -25,7 +26,7 @@ import Control.Monad.Error.Class (catchError, throwError) import Data.Array (head) import Data.Either (Either(..)) import Foreign (Foreign) -import Data.Maybe (Maybe(..)) +import Data.Maybe (Maybe) import Data.Newtype (class Newtype) import Data.Traversable (traverse) import Database.PostgreSQL.Row (class FromSQLRow, class ToSQLRow, Row0(..), Row1(..), fromSQLRow, toSQLRow) @@ -160,6 +161,26 @@ foreign import ffiUnsafeQuery -> Array Foreign -> EffectFnAff (Array (Array Foreign)) -fromRight :: ∀ a b. Either a b -> Maybe b -fromRight (Left _) = Nothing -fromRight (Right a) = Just a +-- | Execute a PostgreSQL query and return its command tag value. +command + :: ∀ i + . ToSQLRow i + => Connection + -> Query i Int + -> i + -> Aff Int +command conn (Query sql) values = + unsafeCommand conn sql (toSQLRow values) + +unsafeCommand + :: Connection + -> String + -> Array Foreign + -> Aff Int +unsafeCommand c s = fromEffectFnAff <<< ffiUnsafeCommand c s + +foreign import ffiUnsafeCommand + :: Connection + -> String + -> Array Foreign + -> EffectFnAff Int diff --git a/test/Main.purs b/test/Main.purs index 17ff9ec..058cbe0 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -18,11 +18,10 @@ import Data.JSDate as JSDate import Data.Maybe (Maybe(..), fromJust) import Data.Newtype (unwrap) import Data.Tuple (Tuple(..)) -import Database.PostgreSQL (Connection, PoolConfiguration, Query(Query), Row0(Row0), Row1(Row1), Row2(Row2), Row3(Row3), Row9(Row9), execute, newPool, query, scalar, withConnection, withTransaction) +import Database.PostgreSQL (Connection, PoolConfiguration, Query(Query), Row0(Row0), Row1(Row1), Row2(Row2), Row3(Row3), Row9(Row9), command, execute, newPool, query, scalar, withConnection, withTransaction) import Effect (Effect) import Effect.Aff (Aff, error, launchAff) import Effect.Class (liftEffect) -import Effect.Console (logShow) import Foreign.Object (Object, fromFoldable) import Math ((%)) import Partial.Unsafe (unsafePartial) @@ -145,6 +144,14 @@ main = void $ launchAff do """) Row0 liftEffect <<< assert $ deleted == [Row2 "pork" true, Row2 "rookworst" true] + test conn "delete returning command tag value" $ do + insertFood + deleted <- command conn (Query """ + DELETE FROM foods + WHERE delicious + """) Row0 + liftEffect <<< assert $ deleted == 2 + test conn "handling instant value" $ do before <- liftEffect $ (unwrap <<< unInstant) <$> now insertFood