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