WIP: call stored pprocedures that emit plain text

The beginning of #114
This commit is contained in:
Joe Nelson
2015-08-20 21:52:46 -07:00
parent f564fb0977
commit bb511f0df2
3 changed files with 38 additions and 2 deletions
+18 -1
View File
@@ -163,6 +163,21 @@ app conf reqBody req =
] $ if echoRequested then encode obj else "" ] $ if echoRequested then encode obj else ""
return $ multipart status201 responses return $ multipart status201 responses
(["rpc", proc], "POST") -> do
let qi = QualifiedIdentifier schema (cs proc)
exists <- doesProcExist schema proc
if exists
then do
row :: Maybe (Identity Text) <- H.maybeEx $ callProc qi $
fromMaybe M.empty (decode reqBody)
return $ responseLBS status200 [textH]
(cs $ fromMaybe "" $ runIdentity <$> row)
else return $ responseLBS status404 [] ""
-- check that proc exists
-- check that arg names are all specified
-- select * from "1".proc(a := "foo"::undefined) where whereT limit limitT
([table], "PUT") -> ([table], "PUT") ->
handleJsonObj reqBody $ \obj -> do handleJsonObj reqBody $ \obj -> do
let qt = qualify table let qt = qualify table
@@ -279,6 +294,9 @@ csvMT = "text/csv"
jsonH :: Header jsonH :: Header
jsonH = (hContentType, jsonMT) jsonH = (hContentType, jsonMT)
textH :: Header
textH = (hContentType, "text/plain")
contentTypeForAccept :: Maybe BS.ByteString -> Maybe BS.ByteString contentTypeForAccept :: Maybe BS.ByteString -> Maybe BS.ByteString
contentTypeForAccept accept contentTypeForAccept accept
| isNothing accept || hasJson = Just jsonMT | isNothing accept || hasJson = Just jsonMT
@@ -295,7 +313,6 @@ bodyForAccept contentType table
| contentType == csvMT = asCsvWithCount table | contentType == csvMT = asCsvWithCount table
| otherwise = asJsonWithCount -- defaults to JSON | otherwise = asJsonWithCount -- defaults to JSON
handleJsonObj :: BL.ByteString -> (Object -> H.Tx P.Postgres s Response) handleJsonObj :: BL.ByteString -> (Object -> H.Tx P.Postgres s Response)
-> H.Tx P.Postgres s Response -> H.Tx P.Postgres s Response
handleJsonObj reqBody handler = do handleJsonObj reqBody handler = do
+8
View File
@@ -10,6 +10,7 @@ import qualified Hasql.Postgres as P
import qualified Hasql.Backend as B import qualified Hasql.Backend as B
import qualified Data.Text as T import qualified Data.Text as T
import qualified Data.HashMap.Strict as H
import Text.Regex.TDFA ( (=~) ) import Text.Regex.TDFA ( (=~) )
import qualified Network.HTTP.Types.URI as Net import qualified Network.HTTP.Types.URI as Net
import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Char8 as BS
@@ -172,6 +173,13 @@ update t cols vals = B.Stmt
<> ")") <> ")")
empty True empty True
callProc :: QualifiedIdentifier -> JSON.Object -> PStmt
callProc qi params = do
let args = T.intercalate "," $ map assignment (H.toList params)
B.Stmt ("select " <> fromQi qi <> "(" <> args <> ")") empty True
where
assignment (n,v) = pgFmtIdent n <> ":=" <> insertableValue v
wherePred :: QualifiedIdentifier -> Net.QueryItem -> PStmt wherePred :: QualifiedIdentifier -> Net.QueryItem -> PStmt
wherePred table (col, predicate) = wherePred table (col, predicate) =
B.Stmt (" " <> pgFmtJsonbPath table (cs col) <> " " <> op <> " " <> B.Stmt (" " <> pgFmtJsonbPath table (cs col) <> " " <> op <> " " <>
+12 -1
View File
@@ -8,7 +8,7 @@ import Data.Text hiding (foldl, map, zipWith, concat)
import Data.Aeson import Data.Aeson
import Data.Functor.Identity import Data.Functor.Identity
import Data.String.Conversions (cs) import Data.String.Conversions (cs)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe, isJust)
import Control.Applicative import Control.Applicative
import qualified Data.Map as Map import qualified Data.Map as Map
@@ -121,6 +121,17 @@ primaryKeyColumns table = do
and kc.table_name = ? |] (qiSchema table) (qiName table) and kc.table_name = ? |] (qiSchema table) (qiName table)
return $ map runIdentity r return $ map runIdentity r
doesProcExist :: Text -> Text -> H.Tx P.Postgres s Bool
doesProcExist schema proc = do
row :: Maybe (Identity Int) <- H.maybeEx $ [H.stmt|
SELECT 1
FROM pg_catalog.pg_namespace n
JOIN pg_catalog.pg_proc p
ON pronamespace = n.oid
WHERE nspname = ?
AND proname = ?
|] schema proc
return $ isJust row
data Table = Table { data Table = Table {
tableSchema :: Text tableSchema :: Text