refactor: rename Proc module to Routine
Assuming that functions=procedures is wrong since pg11, which introduced real stored procedures.
This commit is contained in:
committed by
Steve Chavez
parent
ad7d80a430
commit
feadf59bb3
+1
-1
@@ -46,7 +46,7 @@ library
|
||||
PostgREST.Cors
|
||||
PostgREST.SchemaCache
|
||||
PostgREST.SchemaCache.Identifiers
|
||||
PostgREST.SchemaCache.Proc
|
||||
PostgREST.SchemaCache.Routine
|
||||
PostgREST.SchemaCache.Relationship
|
||||
PostgREST.SchemaCache.Table
|
||||
PostgREST.Error
|
||||
|
||||
@@ -36,9 +36,9 @@ module PostgREST.ApiRequest.Types
|
||||
import PostgREST.MediaType (MediaType (..))
|
||||
import PostgREST.SchemaCache.Identifiers (FieldName,
|
||||
QualifiedIdentifier)
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..))
|
||||
import PostgREST.SchemaCache.Relationship (Relationship,
|
||||
RelationshipsMap)
|
||||
import PostgREST.SchemaCache.Routine (Routine (..))
|
||||
|
||||
import Protolude
|
||||
|
||||
@@ -66,7 +66,7 @@ data SelectItem
|
||||
|
||||
data ApiRequestError
|
||||
= AmbiguousRelBetween Text Text [Relationship]
|
||||
| AmbiguousRpc [ProcDescription]
|
||||
| AmbiguousRpc [Routine]
|
||||
| BinaryFieldError MediaType
|
||||
| MediaTypeError [ByteString]
|
||||
| InvalidBody ByteString
|
||||
@@ -76,7 +76,7 @@ data ApiRequestError
|
||||
| LimitNoOrderError
|
||||
| NotFound
|
||||
| NoRelBetween Text Text (Maybe Text) Text RelationshipsMap
|
||||
| NoRpc Text Text [Text] Bool MediaType Bool [QualifiedIdentifier] [ProcDescription]
|
||||
| NoRpc Text Text [Text] Bool MediaType Bool [QualifiedIdentifier] [Routine]
|
||||
| NotEmbedded Text
|
||||
| PutLimitNotAllowedError
|
||||
| QueryParamError QPError
|
||||
|
||||
@@ -39,12 +39,12 @@ import qualified PostgREST.MediaType as MediaType
|
||||
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
||||
Schema)
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..),
|
||||
ProcParam (..))
|
||||
import PostgREST.SchemaCache.Relationship (Cardinality (..),
|
||||
Junction (..),
|
||||
Relationship (..),
|
||||
RelationshipsMap)
|
||||
import PostgREST.SchemaCache.Routine (Routine (..),
|
||||
RoutineParam (..))
|
||||
import Protolude
|
||||
|
||||
|
||||
@@ -283,7 +283,7 @@ noRelBetweenHint parent child schema allRels = ("Perhaps you meant '" <>) <$>
|
||||
-- to all the overloaded functions' params using the form "param1, param2, param3, ..."
|
||||
-- and shows the best match as hint.
|
||||
--
|
||||
-- >>> let procsDesc = [ProcDescription {pdParams = [ProcParam {ppName="val"}, ProcParam {ppName="param"}, ProcParam {ppName="name"}]}, ProcDescription {pdParams = [ProcParam {ppName="id"}, ProcParam {ppName="attr"}]}]
|
||||
-- >>> let procsDesc = [Routine {pdParams = [RoutineParam {ppName="val"}, RoutineParam {ppName="param"}, RoutineParam {ppName="name"}]}, Routine {pdParams = [RoutineParam {ppName="id"}, RoutineParam {ppName="attr"}]}]
|
||||
--
|
||||
-- >>> noRpcHint "api" "test" ["vall", "pqaram", "nam"] procs procsDesc
|
||||
-- Just "Perhaps you meant to call the function api.test(name, param, val)"
|
||||
@@ -300,7 +300,7 @@ noRelBetweenHint parent child schema allRels = ("Perhaps you meant '" <>) <$>
|
||||
-- >>> noRpcHint "api" "test" ["noclosealternative"] procs procsDesc
|
||||
-- Nothing
|
||||
--
|
||||
noRpcHint :: Text -> Text -> [Text] -> [QualifiedIdentifier] -> [ProcDescription] -> Maybe Text
|
||||
noRpcHint :: Text -> Text -> [Text] -> [QualifiedIdentifier] -> [Routine] -> Maybe Text
|
||||
noRpcHint schema procName params allProcs overloadedProcs =
|
||||
fmap (("Perhaps you meant to call the function " <> schema <> ".") <>) possibleProcs
|
||||
where
|
||||
|
||||
+28
-28
@@ -27,11 +27,11 @@ module PostgREST.Plan
|
||||
) where
|
||||
|
||||
|
||||
import qualified Data.ByteString.Lazy as LBS
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import qualified Data.List as L
|
||||
import qualified Data.Set as S
|
||||
import qualified PostgREST.SchemaCache.Proc as Proc
|
||||
import qualified Data.ByteString.Lazy as LBS
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import qualified Data.List as L
|
||||
import qualified Data.Set as S
|
||||
import qualified PostgREST.SchemaCache.Routine as Routine
|
||||
|
||||
import Data.Either.Combinators (mapLeft, mapRight)
|
||||
import Data.List (delete)
|
||||
@@ -54,16 +54,16 @@ import PostgREST.SchemaCache (SchemaCache (..))
|
||||
import PostgREST.SchemaCache.Identifiers (FieldName,
|
||||
QualifiedIdentifier (..),
|
||||
Schema)
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..),
|
||||
ProcParam (..), ProcsMap,
|
||||
procReturnsCompositeAlias,
|
||||
procReturnsScalar,
|
||||
procReturnsSetOfScalar)
|
||||
import PostgREST.SchemaCache.Relationship (Cardinality (..),
|
||||
Junction (..),
|
||||
Relationship (..),
|
||||
RelationshipsMap,
|
||||
relIsToOne)
|
||||
import PostgREST.SchemaCache.Routine (Routine (..), RoutineMap,
|
||||
RoutineParam (..),
|
||||
funcReturnsCompositeAlias,
|
||||
funcReturnsScalar,
|
||||
funcReturnsSetOfScalar)
|
||||
import PostgREST.SchemaCache.Table (Table (tableName),
|
||||
tablePKCols)
|
||||
|
||||
@@ -95,7 +95,7 @@ data CallReadPlan = CallReadPlan {
|
||||
crReadPlan :: ReadPlanTree
|
||||
, crCallPlan :: CallPlan
|
||||
, crTxMode :: SQL.Mode
|
||||
, crProc :: ProcDescription
|
||||
, crProc :: Routine
|
||||
, crBinField :: Maybe FieldName
|
||||
}
|
||||
|
||||
@@ -117,9 +117,9 @@ callReadPlan identifier conf sCache apiRequest invMethod = do
|
||||
InvGet -> S.fromList $ fst <$> qsParams'
|
||||
InvHead -> S.fromList $ fst <$> qsParams'
|
||||
InvPost -> iColumns apiRequest
|
||||
proc@ProcDescription{..} <- mapLeft ApiRequestError $
|
||||
findProc identifier paramKeys (preferParameters == Just SingleObject) (dbProcs sCache) (iContentMediaType apiRequest) (invMethod == InvPost)
|
||||
let relIdentifier = QualifiedIdentifier pdSchema (fromMaybe pdName $ Proc.procTableName proc) -- done so a set returning function can embed other relations
|
||||
proc@Function{..} <- mapLeft ApiRequestError $
|
||||
findProc identifier paramKeys (preferParameters == Just SingleObject) (dbRoutines sCache) (iContentMediaType apiRequest) (invMethod == InvPost)
|
||||
let relIdentifier = QualifiedIdentifier pdSchema (fromMaybe pdName $ Routine.funcTableName proc) -- done so a set returning function can embed other relations
|
||||
rPlan <- readPlan relIdentifier conf sCache apiRequest
|
||||
let args = case (invMethod, iContentMediaType apiRequest) of
|
||||
(InvGet, _) -> jsonRpcParams proc qsParams'
|
||||
@@ -127,11 +127,11 @@ callReadPlan identifier conf sCache apiRequest invMethod = do
|
||||
(InvPost, MTUrlEncoded) -> maybe mempty (jsonRpcParams proc . payArray) $ iPayload apiRequest
|
||||
(InvPost, _) -> maybe mempty payRaw $ iPayload apiRequest
|
||||
txMode = case (invMethod, pdVolatility) of
|
||||
(InvGet, _) -> SQL.Read
|
||||
(InvHead, _) -> SQL.Read
|
||||
(InvPost, Proc.Stable) -> SQL.Read
|
||||
(InvPost, Proc.Immutable) -> SQL.Read
|
||||
(InvPost, Proc.Volatile) -> SQL.Write
|
||||
(InvGet, _) -> SQL.Read
|
||||
(InvHead, _) -> SQL.Read
|
||||
(InvPost, Routine.Stable) -> SQL.Read
|
||||
(InvPost, Routine.Immutable) -> SQL.Read
|
||||
(InvPost, Routine.Volatile) -> SQL.Write
|
||||
cPlan = callPlan proc apiRequest paramKeys args rPlan
|
||||
binField <- mapLeft ApiRequestError $ binaryField conf (iAcceptMediaType apiRequest) (Just proc) rPlan
|
||||
return $ CallReadPlan rPlan cPlan txMode proc binField
|
||||
@@ -143,7 +143,7 @@ callReadPlan identifier conf sCache apiRequest invMethod = do
|
||||
Search a pg proc by matching name and arguments keys to parameters. Since a function can be overloaded,
|
||||
the name is not enough to find it. An overloaded function can have a different volatility or even a different return type.
|
||||
-}
|
||||
findProc :: QualifiedIdentifier -> S.Set Text -> Bool -> ProcsMap -> MediaType -> Bool -> Either ApiRequestError ProcDescription
|
||||
findProc :: QualifiedIdentifier -> S.Set Text -> Bool -> RoutineMap -> MediaType -> Bool -> Either ApiRequestError Routine
|
||||
findProc qi argumentsKeys paramsAsSingleObject allProcs contentMediaType isInvPost =
|
||||
case matchProc of
|
||||
([], []) -> Left $ NoRpc (qiSchema qi) (qiName qi) (S.toList argumentsKeys) paramsAsSingleObject contentMediaType isInvPost (HM.keys allProcs) lookupProcName
|
||||
@@ -166,7 +166,7 @@ findProc qi argumentsKeys paramsAsSingleObject allProcs contentMediaType isInvPo
|
||||
| otherwise = (ts,fs)
|
||||
-- If the function is called with post and has a single unnamed parameter
|
||||
-- it can be called depending on content type and the parameter type
|
||||
hasSingleUnnamedParam ProcDescription{pdParams=[ProcParam{ppType}]} = isInvPost && case (contentMediaType, ppType) of
|
||||
hasSingleUnnamedParam Function{pdParams=[RoutineParam{ppType}]} = isInvPost && case (contentMediaType, ppType) of
|
||||
(MTApplicationJSON, "json") -> True
|
||||
(MTApplicationJSON, "jsonb") -> True
|
||||
(MTTextPlain, "text") -> True
|
||||
@@ -544,14 +544,14 @@ resolveOrError (Just table) field =
|
||||
Nothing -> Left $ ColumnNotFound (tableName table) field
|
||||
Just typedField -> Right typedField
|
||||
|
||||
callPlan :: ProcDescription -> ApiRequest -> S.Set FieldName -> LBS.ByteString -> ReadPlanTree -> CallPlan
|
||||
callPlan :: Routine -> ApiRequest -> S.Set FieldName -> LBS.ByteString -> ReadPlanTree -> CallPlan
|
||||
callPlan proc ApiRequest{iPreferences=Preferences{..}} paramKeys args readReq = FunctionCall {
|
||||
funCQi = QualifiedIdentifier (pdSchema proc) (pdName proc)
|
||||
, funCParams = callParams
|
||||
, funCArgs = Just args
|
||||
, funCScalar = procReturnsScalar proc
|
||||
, funCSetOfScalar = procReturnsSetOfScalar proc
|
||||
, funCRetCompositeAlias = procReturnsCompositeAlias proc
|
||||
, funCScalar = funcReturnsScalar proc
|
||||
, funCSetOfScalar = funcReturnsSetOfScalar proc
|
||||
, funCRetCompositeAlias = funcReturnsCompositeAlias proc
|
||||
, funCReturning = inferColsEmbedNeeds readReq []
|
||||
}
|
||||
where
|
||||
@@ -616,11 +616,11 @@ addFilterToLogicForest flt lf = Stmnt flt : lf
|
||||
-- | If raw(binary) output is requested, check that MediaType is one of the
|
||||
-- admitted rawMediaTypes and that`?select=...` contains only one field other
|
||||
-- than `*`
|
||||
binaryField :: AppConfig -> MediaType -> Maybe ProcDescription -> ReadPlanTree -> Either ApiRequestError (Maybe FieldName)
|
||||
binaryField :: AppConfig -> MediaType -> Maybe Routine -> ReadPlanTree -> Either ApiRequestError (Maybe FieldName)
|
||||
binaryField AppConfig{configRawMediaTypes} acceptMediaType proc rpTree
|
||||
| isRawMediaType =
|
||||
if (procReturnsScalar <$> proc) == Just True ||
|
||||
(procReturnsSetOfScalar <$> proc) == Just True
|
||||
if (funcReturnsScalar <$> proc) == Just True ||
|
||||
(funcReturnsSetOfScalar <$> proc) == Just True
|
||||
then Right $ Just "pgrst_scalar"
|
||||
else
|
||||
let
|
||||
|
||||
@@ -11,8 +11,8 @@ import qualified Data.ByteString.Lazy as LBS
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import PostgREST.SchemaCache.Identifiers (FieldName,
|
||||
QualifiedIdentifier)
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..),
|
||||
ProcParam (..))
|
||||
import PostgREST.SchemaCache.Routine (Routine (..),
|
||||
RoutineParam (..))
|
||||
|
||||
import Protolude
|
||||
|
||||
@@ -27,11 +27,11 @@ data CallPlan = FunctionCall
|
||||
}
|
||||
|
||||
data CallParams
|
||||
= KeyParams [ProcParam] -- ^ Call with key params: func(a := val1, b:= val2)
|
||||
| OnePosParam ProcParam -- ^ Call with positional params(only one supported): func(val)
|
||||
= 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 :: ProcDescription -> [(Text, Text)] -> LBS.ByteString
|
||||
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
|
||||
@@ -43,11 +43,11 @@ jsonRpcParams proc prms =
|
||||
mergeParams (Variadic a) (Variadic b) = Variadic $ b ++ a
|
||||
mergeParams v _ = v -- repeated params for non-variadic parameters are not merged
|
||||
|
||||
toRpcParamValue :: ProcDescription -> (Text, Text) -> (Text, RpcParamValue)
|
||||
toRpcParamValue :: Routine -> (Text, Text) -> (Text, RpcParamValue)
|
||||
toRpcParamValue proc (k, v) | prmIsVariadic k = (k, Variadic [v])
|
||||
| otherwise = (k, Fixed v)
|
||||
where
|
||||
prmIsVariadic prm = isJust $ find (\ProcParam{ppName, ppVar} -> ppName == prm && ppVar) $ pdParams proc
|
||||
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.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
module PostgREST.Plan.Types
|
||||
( TypedField(..)
|
||||
, resolveTableField
|
||||
|
||||
) where
|
||||
|
||||
import qualified Data.HashMap.Strict.InsOrd as HMI
|
||||
|
||||
+14
-15
@@ -27,12 +27,12 @@ import qualified Hasql.Encoders as HE
|
||||
import qualified Hasql.Statement as SQL
|
||||
import qualified Hasql.Transaction as SQL
|
||||
|
||||
import qualified PostgREST.Error as Error
|
||||
import qualified PostgREST.Query.QueryBuilder as QueryBuilder
|
||||
import qualified PostgREST.Query.Statements as Statements
|
||||
import qualified PostgREST.RangeQuery as RangeQuery
|
||||
import qualified PostgREST.SchemaCache as SchemaCache
|
||||
import qualified PostgREST.SchemaCache.Proc as Proc
|
||||
import qualified PostgREST.Error as Error
|
||||
import qualified PostgREST.Query.QueryBuilder as QueryBuilder
|
||||
import qualified PostgREST.Query.Statements as Statements
|
||||
import qualified PostgREST.RangeQuery as RangeQuery
|
||||
import qualified PostgREST.SchemaCache as SchemaCache
|
||||
import qualified PostgREST.SchemaCache.Routine as Routine
|
||||
|
||||
import Data.Scientific (FPFormat (..), formatScientific, isInteger)
|
||||
|
||||
@@ -59,8 +59,7 @@ import PostgREST.Query.Statements (ResultSet (..))
|
||||
import PostgREST.SchemaCache (SchemaCache (..))
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
||||
Schema)
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..),
|
||||
ProcsMap)
|
||||
import PostgREST.SchemaCache.Routine (Routine (..), RoutineMap)
|
||||
import PostgREST.SchemaCache.Table (TablesMap)
|
||||
|
||||
import Protolude hiding (Handler)
|
||||
@@ -152,14 +151,14 @@ deleteQuery mrPlan apiReq@ApiRequest{..} conf = do
|
||||
optionalRollback conf apiReq
|
||||
pure resultSet
|
||||
|
||||
invokeQuery :: ProcDescription -> CallReadPlan -> ApiRequest -> AppConfig -> PgVersion -> DbHandler ResultSet
|
||||
invokeQuery :: Routine -> CallReadPlan -> ApiRequest -> AppConfig -> PgVersion -> DbHandler ResultSet
|
||||
invokeQuery proc CallReadPlan{crReadPlan, crCallPlan, crBinField} apiReq@ApiRequest{iPreferences=Preferences{..}, ..} conf@AppConfig{..} pgVer = do
|
||||
resultSet <-
|
||||
lift . SQL.statement mempty $
|
||||
Statements.prepareCall
|
||||
(Proc.procReturnsScalar proc)
|
||||
(Proc.procReturnsSingleComposite proc)
|
||||
(Proc.procReturnsSetOfScalar proc)
|
||||
(Routine.funcReturnsScalar proc)
|
||||
(Routine.funcReturnsSingleComposite proc)
|
||||
(Routine.funcReturnsSetOfScalar proc)
|
||||
(QueryBuilder.callPlanToQuery crCallPlan pgVer)
|
||||
(QueryBuilder.readPlanToQuery crReadPlan)
|
||||
(QueryBuilder.readPlanToCountQuery crReadPlan)
|
||||
@@ -172,19 +171,19 @@ invokeQuery proc CallReadPlan{crReadPlan, crCallPlan, crBinField} apiReq@ApiRequ
|
||||
failNotSingular iAcceptMediaType resultSet
|
||||
pure resultSet
|
||||
|
||||
openApiQuery :: SchemaCache -> PgVersion -> AppConfig -> Schema -> DbHandler (Maybe (TablesMap, ProcsMap, Maybe Text))
|
||||
openApiQuery :: SchemaCache -> PgVersion -> AppConfig -> Schema -> DbHandler (Maybe (TablesMap, RoutineMap, Maybe Text))
|
||||
openApiQuery sCache pgVer AppConfig{..} tSchema =
|
||||
lift $ case configOpenApiMode of
|
||||
OAFollowPriv -> do
|
||||
tableAccess <- SQL.statement [tSchema] (SchemaCache.accessibleTables pgVer configDbPreparedStatements)
|
||||
Just <$> ((,,)
|
||||
(HM.filterWithKey (\qi _ -> S.member qi tableAccess) $ SchemaCache.dbTables sCache)
|
||||
<$> SQL.statement tSchema (SchemaCache.accessibleProcs pgVer configDbPreparedStatements)
|
||||
<$> SQL.statement tSchema (SchemaCache.accessibleFuncs pgVer configDbPreparedStatements)
|
||||
<*> SQL.statement tSchema (SchemaCache.schemaDescription configDbPreparedStatements))
|
||||
OAIgnorePriv ->
|
||||
Just <$> ((,,)
|
||||
(HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) $ SchemaCache.dbTables sCache)
|
||||
(HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) $ SchemaCache.dbProcs sCache)
|
||||
(HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch == tSchema) $ SchemaCache.dbRoutines sCache)
|
||||
<$> SQL.statement tSchema (SchemaCache.schemaDescription configDbPreparedStatements))
|
||||
OADisabled ->
|
||||
pure Nothing
|
||||
|
||||
@@ -25,11 +25,11 @@ import PostgREST.ApiRequest.Preferences (PreferResolution (..))
|
||||
import PostgREST.Config.PgVersion (PgVersion, pgVersion110,
|
||||
pgVersion130)
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
|
||||
import PostgREST.SchemaCache.Proc (ProcParam (..))
|
||||
import PostgREST.SchemaCache.Relationship (Cardinality (..),
|
||||
Junction (..),
|
||||
Relationship (..),
|
||||
relIsToOne)
|
||||
import PostgREST.SchemaCache.Routine (RoutineParam (..))
|
||||
|
||||
import PostgREST.ApiRequest.Types
|
||||
import PostgREST.Plan.CallPlan
|
||||
@@ -180,7 +180,7 @@ callPlanToQuery (FunctionCall qi params args returnsScalar returnsSetOfScalar re
|
||||
callIt argument | pgVer < pgVersion130 && pgVer >= pgVersion110 && returnsCompositeAlias = "(SELECT (" <> SQL.sql (fromQi qi) <> "(" <> argument <> ")).*) pgrst_call"
|
||||
| otherwise = SQL.sql (fromQi qi) <> "(" <> argument <> ") pgrst_call"
|
||||
|
||||
fmtParams :: [ProcParam] -> SQL.Snippet
|
||||
fmtParams :: [RoutineParam] -> SQL.Snippet
|
||||
fmtParams prms = SQL.sql $ BS.intercalate ", "
|
||||
((\a -> (if ppVar a then "VARIADIC " else mempty) <> pgFmtIdent (ppName a) <> " := pgrst_body." <> pgFmtIdent (ppName a)) <$> prms)
|
||||
|
||||
|
||||
@@ -50,13 +50,12 @@ import PostgREST.Response.GucHeader (GucHeader, unwrapGucHeader)
|
||||
import PostgREST.SchemaCache (SchemaCache (..))
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
||||
Schema)
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..),
|
||||
ProcVolatility (..),
|
||||
ProcsMap)
|
||||
import PostgREST.SchemaCache.Routine (FuncVolatility (..),
|
||||
Routine (..), RoutineMap)
|
||||
import PostgREST.SchemaCache.Table (Table (..), TablesMap)
|
||||
|
||||
import qualified PostgREST.ApiRequest.Types as ApiRequestTypes
|
||||
import qualified PostgREST.SchemaCache.Proc as Proc
|
||||
import qualified PostgREST.ApiRequest.Types as ApiRequestTypes
|
||||
import qualified PostgREST.SchemaCache.Routine as Routine
|
||||
|
||||
import Protolude hiding (Handler, toS)
|
||||
import Protolude.Conv (toS)
|
||||
@@ -189,7 +188,7 @@ infoIdentResponse identifier sCache =
|
||||
["PATCH" | tableUpdatable table] ++
|
||||
["DELETE" | tableDeletable table]
|
||||
|
||||
infoProcResponse :: ProcDescription -> Wai.Response
|
||||
infoProcResponse :: Routine -> Wai.Response
|
||||
infoProcResponse proc | pdVolatility proc == Volatile = respondInfo "OPTIONS,POST"
|
||||
| otherwise = respondInfo "OPTIONS,GET,HEAD,POST"
|
||||
|
||||
@@ -201,7 +200,7 @@ respondInfo allowHeader =
|
||||
let allOrigins = ("Access-Control-Allow-Origin", "*") in
|
||||
Wai.responseLBS HTTP.status200 [allOrigins, (HTTP.hAllow, allowHeader)] mempty
|
||||
|
||||
invokeResponse :: InvokeMethod -> ProcDescription -> ApiRequest -> ResultSet -> Wai.Response
|
||||
invokeResponse :: InvokeMethod -> Routine -> ApiRequest -> ResultSet -> Wai.Response
|
||||
invokeResponse invMethod proc ctxApiRequest@ApiRequest{..} resultSet = case resultSet of
|
||||
RSStandard {..} -> do
|
||||
let
|
||||
@@ -214,7 +213,7 @@ invokeResponse invMethod proc ctxApiRequest@ApiRequest{..} resultSet = case resu
|
||||
else LBS.fromStrict rsBody
|
||||
headers = [contentRange]
|
||||
|
||||
if Proc.procReturnsVoid proc then
|
||||
if Routine.funcReturnsVoid proc then
|
||||
response HTTP.status204 headers mempty
|
||||
else
|
||||
response status
|
||||
@@ -224,7 +223,7 @@ invokeResponse invMethod proc ctxApiRequest@ApiRequest{..} resultSet = case resu
|
||||
RSPlan plan ->
|
||||
Wai.responseLBS HTTP.status200 (contentTypeHeaders ctxApiRequest) $ LBS.fromStrict plan
|
||||
|
||||
openApiResponse :: Bool -> Maybe (TablesMap, ProcsMap, Maybe Text) -> AppConfig -> SchemaCache -> Schema -> Bool -> Wai.Response
|
||||
openApiResponse :: Bool -> Maybe (TablesMap, RoutineMap, Maybe Text) -> AppConfig -> SchemaCache -> Schema -> Bool -> Wai.Response
|
||||
openApiResponse headersOnly body conf sCache schema negotiatedByProfile =
|
||||
Wai.responseLBS HTTP.status200
|
||||
(MediaType.toContentType MTOpenAPI : maybeToList (profileHeader schema negotiatedByProfile))
|
||||
|
||||
@@ -28,11 +28,11 @@ import PostgREST.Config (AppConfig (..), Proxy (..),
|
||||
isMalformedProxyUri, toURI)
|
||||
import PostgREST.SchemaCache (SchemaCache (..))
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..))
|
||||
import PostgREST.SchemaCache.Proc (ProcDescription (..),
|
||||
ProcParam (..))
|
||||
import PostgREST.SchemaCache.Relationship (Cardinality (..),
|
||||
Relationship (..),
|
||||
RelationshipsMap)
|
||||
import PostgREST.SchemaCache.Routine (Routine (..),
|
||||
RoutineParam (..))
|
||||
import PostgREST.SchemaCache.Table (Column (..), Table (..),
|
||||
TablesMap,
|
||||
tableColumnsList)
|
||||
@@ -42,7 +42,7 @@ import PostgREST.MediaType
|
||||
|
||||
import Protolude hiding (Proxy, get)
|
||||
|
||||
encode :: AppConfig -> SchemaCache -> TablesMap -> HM.HashMap k [ProcDescription] -> Maybe Text -> LBS.ByteString
|
||||
encode :: AppConfig -> SchemaCache -> TablesMap -> HM.HashMap k [Routine] -> Maybe Text -> LBS.ByteString
|
||||
encode conf sCache tables procs schemaDescription =
|
||||
JSON.encode $
|
||||
postgrestSpec
|
||||
@@ -145,7 +145,7 @@ makeProperty tbl rels col = (colName col, Inline s)
|
||||
& type_ .~ toSwaggerType (colType col)
|
||||
& items .~ (SwaggerItemsObject <$> makePropertyItems (colType col))
|
||||
|
||||
makeProcSchema :: ProcDescription -> Schema
|
||||
makeProcSchema :: Routine -> Schema
|
||||
makeProcSchema pd =
|
||||
(mempty :: Schema)
|
||||
& description .~ pdDescription pd
|
||||
@@ -153,8 +153,8 @@ makeProcSchema pd =
|
||||
& properties .~ fromList (fmap makeProcProperty (pdParams pd))
|
||||
& required .~ fmap ppName (filter ppReq (pdParams pd))
|
||||
|
||||
makeProcProperty :: ProcParam -> (Text, Referenced Schema)
|
||||
makeProcProperty (ProcParam n t _ _) = (n, Inline s)
|
||||
makeProcProperty :: RoutineParam -> (Text, Referenced Schema)
|
||||
makeProcProperty (RoutineParam n t _ _) = (n, Inline s)
|
||||
where
|
||||
s = (mempty :: Schema)
|
||||
& type_ .~ toSwaggerType t
|
||||
@@ -180,8 +180,8 @@ makePreferParam ts =
|
||||
"resolution" -> ["resolution=ignore-duplicates", "resolution=merge-duplicates"]
|
||||
_ -> []
|
||||
|
||||
makeProcGetParam :: ProcParam -> Referenced Param
|
||||
makeProcGetParam (ProcParam n t r v) =
|
||||
makeProcGetParam :: RoutineParam -> Referenced Param
|
||||
makeProcGetParam (RoutineParam n t r v) =
|
||||
Inline $ (mempty :: Param)
|
||||
& name .~ n
|
||||
& required ?~ r
|
||||
@@ -206,10 +206,10 @@ makeProcGetParam (ProcParam n t r v) =
|
||||
Nothing -> SwaggerString
|
||||
_ -> fromJust paramType
|
||||
|
||||
makeProcGetParams :: [ProcParam] -> [Referenced Param]
|
||||
makeProcGetParams :: [RoutineParam] -> [Referenced Param]
|
||||
makeProcGetParams = fmap makeProcGetParam
|
||||
|
||||
makeProcPostParams :: ProcDescription -> [Referenced Param]
|
||||
makeProcPostParams :: Routine -> [Referenced Param]
|
||||
makeProcPostParams pd =
|
||||
[ Inline $ (mempty :: Param)
|
||||
& name .~ "args"
|
||||
@@ -340,7 +340,7 @@ makePathItem t = ("/" ++ T.unpack tn, p $ tableInsertable t || tableUpdatable t
|
||||
rs = [ T.intercalate "." ["rowFilter", tn, colName c ] | c <- tableColumnsList t ]
|
||||
ref = Ref . Reference
|
||||
|
||||
makeProcPathItem :: ProcDescription -> (FilePath, PathItem)
|
||||
makeProcPathItem :: Routine -> (FilePath, PathItem)
|
||||
makeProcPathItem pd = ("/rpc/" ++ toS (pdName pd), pe)
|
||||
where
|
||||
-- Use first line of proc description as summary; rest as description (if present)
|
||||
@@ -372,7 +372,7 @@ makeRootPathItem = ("/", p)
|
||||
pr = (mempty :: PathItem) & get ?~ getOp
|
||||
p = pr
|
||||
|
||||
makePathItems :: [ProcDescription] -> [Table] -> InsOrdHashMap FilePath PathItem
|
||||
makePathItems :: [Routine] -> [Table] -> InsOrdHashMap FilePath PathItem
|
||||
makePathItems pds ti = fromList $ makeRootPathItem :
|
||||
fmap makePathItem ti ++ fmap makeProcPathItem pds
|
||||
|
||||
@@ -392,7 +392,7 @@ escapeHostName "*6" = "0.0.0.0"
|
||||
escapeHostName "!6" = "0.0.0.0"
|
||||
escapeHostName h = h
|
||||
|
||||
postgrestSpec :: RelationshipsMap -> [ProcDescription] -> [Table] -> (Text, Text, Integer, Text) -> Maybe Text -> Bool -> Swagger
|
||||
postgrestSpec :: RelationshipsMap -> [Routine] -> [Table] -> (Text, Text, Integer, Text) -> Maybe Text -> Bool -> Swagger
|
||||
postgrestSpec rels pds ti (s, h, p, b) sd allowSecurityDef = (mempty :: Swagger)
|
||||
& basePath ?~ T.unpack b
|
||||
& schemes ?~ [s']
|
||||
|
||||
@@ -22,7 +22,7 @@ module PostgREST.SchemaCache
|
||||
( SchemaCache(..)
|
||||
, querySchemaCache
|
||||
, accessibleTables
|
||||
, accessibleProcs
|
||||
, accessibleFuncs
|
||||
, schemaDescription
|
||||
) where
|
||||
|
||||
@@ -44,15 +44,14 @@ import PostgREST.Config.PgVersion (PgVersion, pgVersion100,
|
||||
import PostgREST.SchemaCache.Identifiers (AccessSet, FieldName,
|
||||
QualifiedIdentifier (..),
|
||||
Schema)
|
||||
import PostgREST.SchemaCache.Proc (PgType (..),
|
||||
ProcDescription (..),
|
||||
ProcParam (..),
|
||||
ProcVolatility (..),
|
||||
ProcsMap, RetType (..))
|
||||
import PostgREST.SchemaCache.Relationship (Cardinality (..),
|
||||
Junction (..),
|
||||
Relationship (..),
|
||||
RelationshipsMap)
|
||||
import PostgREST.SchemaCache.Routine (FuncVolatility (..),
|
||||
PgType (..), RetType (..),
|
||||
Routine (..), RoutineMap,
|
||||
RoutineParam (..))
|
||||
import PostgREST.SchemaCache.Table (Column (..), ColumnMap,
|
||||
Table (..), TablesMap)
|
||||
|
||||
@@ -62,7 +61,7 @@ import Protolude
|
||||
data SchemaCache = SchemaCache
|
||||
{ dbTables :: TablesMap
|
||||
, dbRelationships :: RelationshipsMap
|
||||
, dbProcs :: ProcsMap
|
||||
, dbRoutines :: RoutineMap
|
||||
}
|
||||
deriving (Generic, JSON.ToJSON)
|
||||
|
||||
@@ -111,7 +110,7 @@ querySchemaCache schemas extraSearchPath prepared = do
|
||||
tabs <- SQL.statement schemas $ allTables pgVer prepared
|
||||
keyDeps <- SQL.statement (schemas, extraSearchPath) $ allViewsKeyDependencies prepared
|
||||
m2oRels <- SQL.statement mempty $ allM2OandO2ORels pgVer prepared
|
||||
procs <- SQL.statement schemas $ allProcs pgVer prepared
|
||||
funcs <- SQL.statement schemas $ allFunctions pgVer prepared
|
||||
cRels <- SQL.statement mempty $ allComputedRels prepared
|
||||
|
||||
let tabsWViewsPks = addViewPrimaryKeys tabs keyDeps
|
||||
@@ -120,7 +119,7 @@ querySchemaCache schemas extraSearchPath prepared = do
|
||||
return $ removeInternal schemas $ SchemaCache {
|
||||
dbTables = tabsWViewsPks
|
||||
, dbRelationships = getOverrideRelationshipsMap rels cRels
|
||||
, dbProcs = procs
|
||||
, dbRoutines = funcs
|
||||
}
|
||||
|
||||
-- | overrides detected relationships with the computed relationships and gets the RelationshipsMap
|
||||
@@ -150,7 +149,7 @@ removeInternal schemas dbStruct =
|
||||
dbTables = HM.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch `elem` schemas) $ dbTables dbStruct
|
||||
, dbRelationships = filter (\r -> qiSchema (relForeignTable r) `elem` schemas && not (hasInternalJunction r)) <$>
|
||||
HM.filterWithKey (\(QualifiedIdentifier sch _, _) _ -> sch `elem` schemas ) (dbRelationships dbStruct)
|
||||
, dbProcs = dbProcs dbStruct -- procs are only obtained from the exposed schemas, no need to filter them.
|
||||
, dbRoutines = dbRoutines dbStruct -- procs are only obtained from the exposed schemas, no need to filter them.
|
||||
}
|
||||
where
|
||||
hasInternalJunction ComputedRelationship{} = False
|
||||
@@ -228,17 +227,17 @@ viewKeyDepFromRow (s1,t1,s2,v2,cons,consType,sCols) = ViewKeyDependency (Qualifi
|
||||
| consType == "f" = FKDep
|
||||
| otherwise = FKDepRef -- f_ref, we build this type in the query
|
||||
|
||||
decodeProcs :: HD.Result ProcsMap
|
||||
decodeProcs =
|
||||
-- Duplicate rows for a function means they're overloaded, order these by least args according to ProcDescription Ord instance
|
||||
map sort . HM.fromListWith (++) . map ((\(x,y) -> (x, [y])) . addKey) <$> HD.rowList procRow
|
||||
decodeFuncs :: HD.Result RoutineMap
|
||||
decodeFuncs =
|
||||
-- Duplicate rows for a function means they're overloaded, order these by least args according to Routine Ord instance
|
||||
map sort . HM.fromListWith (++) . map ((\(x,y) -> (x, [y])) . addKey) <$> HD.rowList funcRow
|
||||
where
|
||||
procRow = ProcDescription
|
||||
funcRow = Function
|
||||
<$> column HD.text
|
||||
<*> column HD.text
|
||||
<*> nullableColumn HD.text
|
||||
<*> compositeArrayColumn
|
||||
(ProcParam
|
||||
(RoutineParam
|
||||
<$> compositeField HD.text
|
||||
<*> compositeField HD.text
|
||||
<*> compositeField HD.bool
|
||||
@@ -253,7 +252,7 @@ decodeProcs =
|
||||
<*> (parseVolatility <$> column HD.char)
|
||||
<*> column HD.bool
|
||||
|
||||
addKey :: ProcDescription -> (QualifiedIdentifier, ProcDescription)
|
||||
addKey :: Routine -> (QualifiedIdentifier, Routine)
|
||||
addKey pd = (QualifiedIdentifier (pdSchema pd) (pdName pd), pd)
|
||||
|
||||
parseRetType :: Text -> Text -> Bool -> Bool -> Bool -> Bool -> RetType
|
||||
@@ -267,23 +266,23 @@ decodeProcs =
|
||||
| isComposite = Composite qi isCompositeAlias
|
||||
| otherwise = Scalar False
|
||||
|
||||
parseVolatility :: Char -> ProcVolatility
|
||||
parseVolatility :: Char -> FuncVolatility
|
||||
parseVolatility v | v == 'i' = Immutable
|
||||
| v == 's' = Stable
|
||||
| otherwise = Volatile -- only 'v' can happen here
|
||||
|
||||
allProcs :: PgVersion -> Bool -> SQL.Statement [Schema] ProcsMap
|
||||
allProcs pgVer = SQL.Statement sql (arrayParam HE.text) decodeProcs
|
||||
allFunctions :: PgVersion -> Bool -> SQL.Statement [Schema] RoutineMap
|
||||
allFunctions pgVer = SQL.Statement sql (arrayParam HE.text) decodeFuncs
|
||||
where
|
||||
sql = procsSqlQuery pgVer <> " AND pn.nspname = ANY($1)"
|
||||
sql = funcsSqlQuery pgVer <> " AND pn.nspname = ANY($1)"
|
||||
|
||||
accessibleProcs :: PgVersion -> Bool -> SQL.Statement Schema ProcsMap
|
||||
accessibleProcs pgVer = SQL.Statement sql (param HE.text) decodeProcs
|
||||
accessibleFuncs :: PgVersion -> Bool -> SQL.Statement Schema RoutineMap
|
||||
accessibleFuncs pgVer = SQL.Statement sql (param HE.text) decodeFuncs
|
||||
where
|
||||
sql = procsSqlQuery pgVer <> " AND pn.nspname = $1 AND has_function_privilege(p.oid, 'execute')"
|
||||
sql = funcsSqlQuery pgVer <> " AND pn.nspname = $1 AND has_function_privilege(p.oid, 'execute')"
|
||||
|
||||
procsSqlQuery :: PgVersion -> SqlQuery
|
||||
procsSqlQuery pgVer = [q|
|
||||
funcsSqlQuery :: PgVersion -> SqlQuery
|
||||
funcsSqlQuery pgVer = [q|
|
||||
-- Recursively get the base types of domains
|
||||
WITH
|
||||
base_types AS (
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
{-# LANGUAGE DeriveAnyClass #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
|
||||
module PostgREST.SchemaCache.Proc
|
||||
( PgType(..)
|
||||
, ProcDescription(..)
|
||||
, ProcParam(..)
|
||||
, ProcVolatility(..)
|
||||
, ProcsMap
|
||||
, RetType(..)
|
||||
, procReturnsScalar
|
||||
, procReturnsSetOfScalar
|
||||
, procReturnsSingleComposite
|
||||
, procReturnsVoid
|
||||
, procTableName
|
||||
, procReturnsCompositeAlias
|
||||
) where
|
||||
|
||||
import qualified Data.Aeson as JSON
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
||||
Schema, TableName)
|
||||
|
||||
import Protolude
|
||||
|
||||
data PgType
|
||||
= Scalar Bool -- True if the type is void
|
||||
| Composite QualifiedIdentifier Bool -- True if the composite is a domain alias(used to work around a bug in pg 11 and 12, see QueryBuilder.hs)
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
data RetType
|
||||
= Single PgType
|
||||
| SetOf PgType
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
data ProcVolatility
|
||||
= Volatile
|
||||
| Stable
|
||||
| Immutable
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
data ProcDescription = ProcDescription
|
||||
{ pdSchema :: Schema
|
||||
, pdName :: Text
|
||||
, pdDescription :: Maybe Text
|
||||
, pdParams :: [ProcParam]
|
||||
, pdReturnType :: RetType
|
||||
, pdVolatility :: ProcVolatility
|
||||
, pdHasVariadic :: Bool
|
||||
}
|
||||
deriving (Eq, Generic, JSON.ToJSON)
|
||||
|
||||
data ProcParam = ProcParam
|
||||
{ ppName :: Text
|
||||
, ppType :: Text
|
||||
, ppReq :: Bool
|
||||
, ppVar :: Bool
|
||||
}
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
-- Order by least number of params in the case of overloaded functions
|
||||
instance Ord ProcDescription where
|
||||
ProcDescription schema1 name1 des1 prms1 rt1 vol1 hasVar1 `compare` ProcDescription schema2 name2 des2 prms2 rt2 vol2 hasVar2
|
||||
| schema1 == schema2 && name1 == name2 && length prms1 < length prms2 = LT
|
||||
| schema2 == schema2 && name1 == name2 && length prms1 > length prms2 = GT
|
||||
| otherwise = (schema1, name1, des1, prms1, rt1, vol1, hasVar1) `compare` (schema2, name2, des2, prms2, rt2, vol2, hasVar2)
|
||||
|
||||
-- | A map of all procs, all of which can be overloaded(one entry will have more than one ProcDescription).
|
||||
-- | It uses a HashMap for a faster lookup.
|
||||
type ProcsMap = HM.HashMap QualifiedIdentifier [ProcDescription]
|
||||
|
||||
procReturnsScalar :: ProcDescription -> Bool
|
||||
procReturnsScalar proc = case proc of
|
||||
ProcDescription{pdReturnType = Single (Scalar _)} -> True
|
||||
_ -> False
|
||||
|
||||
procReturnsSetOfScalar :: ProcDescription -> Bool
|
||||
procReturnsSetOfScalar proc = case proc of
|
||||
ProcDescription{pdReturnType = SetOf (Scalar _)} -> True
|
||||
_ -> False
|
||||
|
||||
procReturnsCompositeAlias :: ProcDescription -> Bool
|
||||
procReturnsCompositeAlias proc = case proc of
|
||||
ProcDescription{pdReturnType = Single (Composite _ True)} -> True
|
||||
ProcDescription{pdReturnType = SetOf (Composite _ True)} -> True
|
||||
_ -> False
|
||||
|
||||
procReturnsSingleComposite :: ProcDescription -> Bool
|
||||
procReturnsSingleComposite proc = case proc of
|
||||
ProcDescription{pdReturnType = Single (Composite _ _)} -> True
|
||||
_ -> False
|
||||
|
||||
procReturnsVoid :: ProcDescription -> Bool
|
||||
procReturnsVoid proc = case proc of
|
||||
ProcDescription{pdReturnType = Single (Scalar True)} -> True
|
||||
_ -> False
|
||||
|
||||
procTableName :: ProcDescription -> Maybe TableName
|
||||
procTableName proc = case pdReturnType proc of
|
||||
SetOf (Composite qi _) -> Just $ qiName qi
|
||||
Single (Composite qi _) -> Just $ qiName qi
|
||||
_ -> Nothing
|
||||
@@ -0,0 +1,103 @@
|
||||
{-# LANGUAGE DeriveAnyClass #-}
|
||||
{-# LANGUAGE DeriveGeneric #-}
|
||||
|
||||
module PostgREST.SchemaCache.Routine
|
||||
( PgType(..)
|
||||
, Routine(..)
|
||||
, RoutineParam(..)
|
||||
, FuncVolatility(..)
|
||||
, RoutineMap
|
||||
, RetType(..)
|
||||
, funcReturnsScalar
|
||||
, funcReturnsSetOfScalar
|
||||
, funcReturnsSingleComposite
|
||||
, funcReturnsVoid
|
||||
, funcTableName
|
||||
, funcReturnsCompositeAlias
|
||||
) where
|
||||
|
||||
import qualified Data.Aeson as JSON
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
|
||||
import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..),
|
||||
Schema, TableName)
|
||||
|
||||
import Protolude
|
||||
|
||||
data PgType
|
||||
= Scalar Bool -- True if the type is void
|
||||
| Composite QualifiedIdentifier Bool -- True if the composite is a domain alias(used to work around a bug in pg 11 and 12, see QueryBuilder.hs)
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
data RetType
|
||||
= Single PgType
|
||||
| SetOf PgType
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
data FuncVolatility
|
||||
= Volatile
|
||||
| Stable
|
||||
| Immutable
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
data Routine = Function
|
||||
{ pdSchema :: Schema
|
||||
, pdName :: Text
|
||||
, pdDescription :: Maybe Text
|
||||
, pdParams :: [RoutineParam]
|
||||
, pdReturnType :: RetType
|
||||
, pdVolatility :: FuncVolatility
|
||||
, pdHasVariadic :: Bool
|
||||
}
|
||||
deriving (Eq, Generic, JSON.ToJSON)
|
||||
|
||||
data RoutineParam = RoutineParam
|
||||
{ ppName :: Text
|
||||
, ppType :: Text
|
||||
, ppReq :: Bool
|
||||
, ppVar :: Bool
|
||||
}
|
||||
deriving (Eq, Ord, Generic, JSON.ToJSON)
|
||||
|
||||
-- Order by least number of params in the case of overloaded functions
|
||||
instance Ord Routine where
|
||||
Function schema1 name1 des1 prms1 rt1 vol1 hasVar1 `compare` Function schema2 name2 des2 prms2 rt2 vol2 hasVar2
|
||||
| schema1 == schema2 && name1 == name2 && length prms1 < length prms2 = LT
|
||||
| schema2 == schema2 && name1 == name2 && length prms1 > length prms2 = GT
|
||||
| otherwise = (schema1, name1, des1, prms1, rt1, vol1, hasVar1) `compare` (schema2, name2, des2, prms2, rt2, vol2, hasVar2)
|
||||
|
||||
-- | A map of all procs, all of which can be overloaded(one entry will have more than one Routine).
|
||||
-- | It uses a HashMap for a faster lookup.
|
||||
type RoutineMap = HM.HashMap QualifiedIdentifier [Routine]
|
||||
|
||||
funcReturnsScalar :: Routine -> Bool
|
||||
funcReturnsScalar proc = case proc of
|
||||
Function{pdReturnType = Single (Scalar _)} -> True
|
||||
_ -> False
|
||||
|
||||
funcReturnsSetOfScalar :: Routine -> Bool
|
||||
funcReturnsSetOfScalar proc = case proc of
|
||||
Function{pdReturnType = SetOf (Scalar _)} -> True
|
||||
_ -> False
|
||||
|
||||
funcReturnsCompositeAlias :: Routine -> Bool
|
||||
funcReturnsCompositeAlias proc = case proc of
|
||||
Function{pdReturnType = Single (Composite _ True)} -> True
|
||||
Function{pdReturnType = SetOf (Composite _ True)} -> True
|
||||
_ -> False
|
||||
|
||||
funcReturnsSingleComposite :: Routine -> Bool
|
||||
funcReturnsSingleComposite proc = case proc of
|
||||
Function{pdReturnType = Single (Composite _ _)} -> True
|
||||
_ -> False
|
||||
|
||||
funcReturnsVoid :: Routine -> Bool
|
||||
funcReturnsVoid proc = case proc of
|
||||
Function{pdReturnType = Single (Scalar True)} -> True
|
||||
_ -> False
|
||||
|
||||
funcTableName :: Routine -> Maybe TableName
|
||||
funcTableName proc = case pdReturnType proc of
|
||||
SetOf (Composite qi _) -> Just $ qiName qi
|
||||
Single (Composite qi _) -> Just $ qiName qi
|
||||
_ -> Nothing
|
||||
Reference in New Issue
Block a user