WIP: call stored pprocedures that emit plain text
The beginning of #114
This commit is contained in:
+18
-1
@@ -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
|
||||||
|
|||||||
@@ -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 <> " " <>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user