66 lines
2.7 KiB
Haskell
66 lines
2.7 KiB
Haskell
{-# LANGUAGE NamedFieldPuns #-}
|
|
module PostgREST.Plan.CallPlan
|
|
( CallPlan(..)
|
|
, CallParams(..)
|
|
, CallArgs(..)
|
|
, RpcParamValue(..)
|
|
, toRpcParams
|
|
)
|
|
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 :: CallArgs
|
|
, funCScalar :: Bool
|
|
, funCSetOfScalar :: Bool
|
|
, funCRetCompositeAlias :: Bool
|
|
, funCFilterFields :: Set FieldName
|
|
, funCReturning :: Set 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)
|
|
|
|
data CallArgs
|
|
= DirectArgs (HM.HashMap Text RpcParamValue)
|
|
| JsonArgs (Maybe LBS.ByteString)
|
|
|
|
-- | 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
|
|
-- Not possible to get here anymore. Variadic arguments are only supported for
|
|
-- true variadic arguments, but the toJSON instance is only used for the "single unnamed json argument" case.
|
|
toJSON (Variadic v) = JSON.toJSON v
|
|
|
|
-- | Convert rpc params `/rpc/func?a=val1&b=val2` to json `{"a": "val1", "b": "val2"}
|
|
toRpcParams :: Routine -> [(Text, Text)] -> HM.HashMap Text RpcParamValue
|
|
toRpcParams proc prms =
|
|
if not $ pdHasVariadic proc then -- if proc has no variadic param, save steps and directly convert to map
|
|
HM.fromList $ second Fixed <$> prms
|
|
else
|
|
HM.fromListWith mergeParams $ toRpcParamValue proc <$> prms
|
|
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
|