refactor: Replace elem with pattern matching to highlight missing code coverage

Signed-off-by: Wolfgang Walther <walther@technowledgy.de>
This commit is contained in:
Wolfgang Walther
2022-01-28 19:26:33 +01:00
committed by Wolfgang Walther
parent 271c329677
commit 8a722e2cfe
2 changed files with 34 additions and 28 deletions
+4 -4
View File
@@ -65,7 +65,7 @@ createWriteStatement selectQuery mutateQuery wantSingle isInsert asCsv rep pKeys
"FROM (" <> selectF <> ") _postgrest_t"
locF =
if isInsert && rep `elem` [Full, HeadersOnly]
if isInsert && rep /= None
then BS.unwords [
"CASE WHEN pg_catalog.count(_postgrest_t) = 1",
"THEN coalesce(" <> locationF pKeys <> ", " <> noLocationF <> ")",
@@ -74,15 +74,15 @@ createWriteStatement selectQuery mutateQuery wantSingle isInsert asCsv rep pKeys
else noLocationF
bodyF
| rep `elem` [None, HeadersOnly] = "''"
| rep /= Full = "''"
| asCsv = asCsvF
| wantSingle = asJsonSingleF False
| otherwise = asJsonF False
selectF
-- prevent using any of the column names in ?select= when no response is returned from the CTE
| rep `elem` [None, HeadersOnly] = SQL.sql ("SELECT * FROM " <> sourceCTEName)
| otherwise = selectQuery
| rep /= Full = SQL.sql ("SELECT * FROM " <> sourceCTEName)
| otherwise = selectQuery
decodeStandard :: HD.Result ResultsWithCount
decodeStandard =
+30 -24
View File
@@ -214,11 +214,11 @@ apiRequest conf@AppConfig{..} dbStructure req reqBody queryparams@QueryParams{..
_ -> False
contentType = maybe CTApplicationJSON ContentType.decodeContentType $ lookupHeader "content-type"
columns =
if action `elem` [ActionCreate, ActionUpdate, ActionInvoke InvPost] then
qsColumns
else
Nothing
columns = case action of
ActionCreate -> qsColumns
ActionUpdate -> qsColumns
ActionInvoke InvPost -> qsColumns
_ -> Nothing
payloadColumns =
case (contentType, action) of
@@ -230,24 +230,23 @@ apiRequest conf@AppConfig{..} dbStructure req reqBody queryparams@QueryParams{..
(Just RawJSON{}, Just cls) -> cls
_ -> S.empty
payload :: Either ByteString Payload
payload = case contentType of
CTApplicationJSON ->
payload = case (contentType, isTargetingProc) of
(CTApplicationJSON, _) ->
if isJust columns
then Right $ RawJSON reqBody
else note "All object keys must match" . payloadAttributes reqBody
=<< if LBS.null reqBody && isTargetingProc
then Right emptyObject
else first BS.pack $ JSON.eitherDecode reqBody
CTTextCSV -> do
(CTTextCSV, _) -> do
json <- csvToJson <$> first BS.pack (CSV.decodeByName reqBody)
note "All lines must have same number of fields" $ payloadAttributes (JSON.encode json) json
CTUrlEncoded ->
(CTUrlEncoded, _) ->
let paramsMap = M.fromList $ (T.decodeUtf8 *** JSON.String . T.decodeUtf8) <$> parseSimpleQuery (LBS.toStrict reqBody) in
Right $ ProcessedJSON (JSON.encode paramsMap) $ S.fromList (M.keys paramsMap)
ct ->
if isTargetingProc && ct `elem` [CTTextPlain, CTOctetStream]
then Right $ RawPay reqBody
else Left $ "Content-Type not acceptable: " <> ContentType.toMime ct
(CTTextPlain, True) -> Right $ RawPay reqBody
(CTOctetStream, True) -> Right $ RawPay reqBody
(ct, _) -> Left $ "Content-Type not acceptable: " <> ContentType.toMime ct
topLevelRange = fromMaybe allRange $ M.lookup "limit" ranges -- if no limit is specified, get all the request rows
action =
case method of
@@ -297,9 +296,13 @@ apiRequest conf@AppConfig{..} dbStructure req reqBody queryparams@QueryParams{..
| otherwise -> Right $ TargetIdent $ QualifiedIdentifier pSchema pName
PathUnknown -> Right TargetUnknown
shouldParsePayload = case (contentType, action) of
(CTUrlEncoded, ActionInvoke InvPost) -> False
(_, act) -> act `elem` [ActionCreate, ActionUpdate, ActionSingleUpsert, ActionInvoke InvPost]
shouldParsePayload = case (action, contentType) of
(ActionCreate, _) -> True
(ActionInvoke InvPost, CTUrlEncoded) -> False
(ActionInvoke InvPost, _) -> True
(ActionSingleUpsert, _) -> True
(ActionUpdate, _) -> True
_ -> False
relevantPayload = case (contentType, action) of
-- Though ActionInvoke GET/HEAD doesn't really have a payload, we use the payload variable as a way
-- to store the query string arguments to the function.
@@ -440,18 +443,21 @@ findProc qi argumentsKeys paramsAsSingleObject allProcs contentType isInvPost =
| 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 proc = isInvPost && case pdParams proc of
[ProcParam "" ppType _ _]
| contentType == CTApplicationJSON -> ppType `elem` ["json", "jsonb"]
| contentType == CTTextPlain -> ppType == "text"
| contentType == CTOctetStream -> ppType == "bytea"
| otherwise -> False
hasSingleUnnamedParam ProcDescription{pdParams=[ProcParam{ppType}]} = isInvPost && case (contentType, ppType) of
(CTApplicationJSON, "json") -> True
(CTApplicationJSON, "jsonb") -> True
(CTTextPlain, "text") -> True
(CTOctetStream, "bytea") -> True
_ -> False
hasSingleUnnamedParam _ = False
matchesParams proc =
let params = pdParams proc in
let
params = pdParams proc
firstType = (ppType <$> headMay params)
in
-- exceptional case for Prefer: params=single-object
if paramsAsSingleObject
then length params == 1 && (ppType <$> headMay params) `elem` [Just "json", Just "jsonb"]
then length params == 1 && (firstType == Just "json" || firstType == Just "jsonb")
-- If the function has no parameters, the arguments keys must be empty as well
else if null params
then null argumentsKeys && contentType `notElem` [CTTextPlain, CTOctetStream]