Assuming that functions=procedures is wrong since pg11, which introduced real stored procedures.
58 lines
2.4 KiB
Haskell
58 lines
2.4 KiB
Haskell
{-# LANGUAGE NamedFieldPuns #-}
|
|
module PostgREST.Plan.CallPlan
|
|
( CallPlan(..)
|
|
, CallParams(..)
|
|
, jsonRpcParams
|
|
)
|
|
where
|
|
|
|
import qualified Data.Aeson as JSON
|
|
import qualified Data.ByteString.Lazy as LBS
|
|
import qualified Data.HashMap.Strict as HM
|
|
import PostgREST.SchemaCache.Identifiers (FieldName,
|
|
QualifiedIdentifier)
|
|
import PostgREST.SchemaCache.Routine (Routine (..),
|
|
RoutineParam (..))
|
|
|
|
import Protolude
|
|
|
|
data CallPlan = FunctionCall
|
|
{ funCQi :: QualifiedIdentifier
|
|
, funCParams :: CallParams
|
|
, funCArgs :: Maybe LBS.ByteString
|
|
, funCScalar :: Bool
|
|
, funCSetOfScalar :: Bool
|
|
, funCRetCompositeAlias :: Bool
|
|
, funCReturning :: [FieldName]
|
|
}
|
|
|
|
data CallParams
|
|
= KeyParams [RoutineParam] -- ^ Call with key params: func(a := val1, b:= val2)
|
|
| OnePosParam RoutineParam -- ^ Call with positional params(only one supported): func(val)
|
|
|
|
-- | Convert rpc params `/rpc/func?a=val1&b=val2` to json `{"a": "val1", "b": "val2"}
|
|
jsonRpcParams :: Routine -> [(Text, Text)] -> LBS.ByteString
|
|
jsonRpcParams proc prms =
|
|
if not $ pdHasVariadic proc then -- if proc has no variadic param, save steps and directly convert to json
|
|
JSON.encode $ HM.fromList $ second JSON.toJSON <$> prms
|
|
else
|
|
let paramsMap = HM.fromListWith mergeParams $ toRpcParamValue proc <$> prms in
|
|
JSON.encode paramsMap
|
|
where
|
|
mergeParams :: RpcParamValue -> RpcParamValue -> RpcParamValue
|
|
mergeParams (Variadic a) (Variadic b) = Variadic $ b ++ a
|
|
mergeParams v _ = v -- repeated params for non-variadic parameters are not merged
|
|
|
|
toRpcParamValue :: Routine -> (Text, Text) -> (Text, RpcParamValue)
|
|
toRpcParamValue proc (k, v) | prmIsVariadic k = (k, Variadic [v])
|
|
| otherwise = (k, Fixed v)
|
|
where
|
|
prmIsVariadic prm = isJust $ find (\RoutineParam{ppName, ppVar} -> ppName == prm && ppVar) $ pdParams proc
|
|
|
|
-- | RPC query param value `/rpc/func?v=<value>`, used for VARIADIC functions on form-urlencoded POST and GETs
|
|
-- | It can be fixed `?v=1` or repeated `?v=1&v=2&v=3.
|
|
data RpcParamValue = Fixed Text | Variadic [Text]
|
|
instance JSON.ToJSON RpcParamValue where
|
|
toJSON (Fixed v) = JSON.toJSON v
|
|
toJSON (Variadic v) = JSON.toJSON v
|