refactor: wrap proc logic in asJsonF

* add explicit logic for returning setof scalars
This commit is contained in:
steve-chavez
2023-04-04 19:55:10 -05:00
committed by Steve Chavez
parent d945e8c06a
commit 16f2849724
7 changed files with 41 additions and 30 deletions
+5 -2
View File
@@ -56,7 +56,8 @@ import PostgREST.SchemaCache.Identifiers (FieldName,
Schema)
import PostgREST.SchemaCache.Proc (ProcDescription (..),
ProcParam (..), ProcsMap,
procReturnsScalar)
procReturnsScalar,
procReturnsSetOfScalar)
import PostgREST.SchemaCache.Relationship (Cardinality (..),
Junction (..),
Relationship (..),
@@ -548,6 +549,7 @@ callPlan proc ApiRequest{iPreferences=Preferences{..}} paramKeys args readReq =
, funCParams = callParams
, funCArgs = Just args
, funCScalar = procReturnsScalar proc
, funCSetOfScalar = procReturnsSetOfScalar proc
, funCReturning = inferColsEmbedNeeds readReq []
}
where
@@ -615,7 +617,8 @@ addFilterToLogicForest flt lf = Stmnt flt : lf
binaryField :: AppConfig -> MediaType -> Maybe ProcDescription -> ReadPlanTree -> Either ApiRequestError (Maybe FieldName)
binaryField AppConfig{configRawMediaTypes} acceptMediaType proc rpTree
| isRawMediaType =
if (procReturnsScalar <$> proc) == Just True
if (procReturnsScalar <$> proc) == Just True ||
(procReturnsSetOfScalar <$> proc) == Just True
then Right $ Just "pgrst_scalar"
else
let
+6 -5
View File
@@ -17,11 +17,12 @@ import PostgREST.SchemaCache.Proc (ProcDescription (..),
import Protolude
data CallPlan = FunctionCall
{ funCQi :: QualifiedIdentifier
, funCParams :: CallParams
, funCArgs :: Maybe LBS.ByteString
, funCScalar :: Bool
, funCReturning :: [FieldName]
{ funCQi :: QualifiedIdentifier
, funCParams :: CallParams
, funCArgs :: Maybe LBS.ByteString
, funCScalar :: Bool
, funCSetOfScalar :: Bool
, funCReturning :: [FieldName]
}
data CallParams
+2 -1
View File
@@ -158,7 +158,8 @@ invokeQuery proc CallReadPlan{crReadPlan, crCallPlan, crBinField} apiReq@ApiRequ
lift . SQL.statement mempty $
Statements.prepareCall
(Proc.procReturnsScalar proc)
(Proc.procReturnsSingle proc)
(Proc.procReturnsSingleComposite proc)
(Proc.procReturnsSetOfScalar proc)
(QueryBuilder.callPlanToQuery crCallPlan)
(QueryBuilder.readPlanToQuery crReadPlan)
(QueryBuilder.readPlanToCountQuery crReadPlan)
+2 -2
View File
@@ -164,8 +164,8 @@ mutatePlanToQuery (Delete mainQi logicForest range ordts returnings)
(whereRangeIdF, rangeIdF) = mutRangeF mainQi (fst . otTerm <$> ordts)
callPlanToQuery :: CallPlan -> SQL.Snippet
callPlanToQuery (FunctionCall qi params args returnsScalar returnings) =
"SELECT " <> (if returnsScalar then "pgrst_call AS pgrst_scalar " else returnedColumns) <> " " <>
callPlanToQuery (FunctionCall qi params args returnsScalar returnsSetOfScalar returnings) =
"SELECT " <> (if returnsScalar || returnsSetOfScalar then "pgrst_call AS pgrst_scalar " else returnedColumns) <> " " <>
fromCall
where
fromCall = case params of
+7 -5
View File
@@ -178,16 +178,18 @@ asCsvF = asCsvHeaderF <> " || '\n' || " <> asCsvBodyF
")"
asCsvBodyF = "coalesce(string_agg(substring(_postgrest_t::text, 2, length(_postgrest_t::text) - 2), '\n'), '')"
asJsonF :: Bool -> SqlFragment
asJsonF returnsScalar
| returnsScalar = "coalesce(json_agg(_postgrest_t.pgrst_scalar), '[]')"
| otherwise = "coalesce(json_agg(_postgrest_t), '[]')"
asJsonSingleF :: Bool -> SqlFragment
asJsonSingleF returnsScalar
| returnsScalar = "coalesce(json_agg(_postgrest_t.pgrst_scalar)->0, 'null')"
| otherwise = "coalesce(json_agg(_postgrest_t)->0, 'null')"
asJsonF :: Bool -> Bool -> Bool -> SqlFragment
asJsonF returnsScalar returnsSetOfScalar returnsSingleComposite
| returnsSingleComposite = "coalesce(json_agg(_postgrest_t)->0, 'null')"
| returnsScalar = "coalesce(json_agg(_postgrest_t.pgrst_scalar)->0, 'null')"
| returnsSetOfScalar = "coalesce(json_agg(_postgrest_t.pgrst_scalar), '[]')"
| otherwise = "coalesce(json_agg(_postgrest_t), '[]')"
asXmlF :: FieldName -> SqlFragment
asXmlF fieldName = "coalesce(xmlagg(_postgrest_t." <> pgFmtIdent fieldName <> "), '')"
+5 -6
View File
@@ -87,7 +87,7 @@ prepareWrite selectQuery mutateQuery isInsert mt rep pKeys =
| getMediaType mt == MTTextCSV = asCsvF
| getMediaType mt == MTGeoJSON = asGeoJsonF
| getMediaType mt == MTSingularJSON = asJsonSingleF False
| otherwise = asJsonF False
| otherwise = asJsonF False False False
selectF
-- prevent using any of the column names in ?select= when no response is returned from the CTE
@@ -123,17 +123,17 @@ prepareRead selectQuery countQuery countTotal mt binaryField =
| getMediaType mt == MTGeoJSON = asGeoJsonF
| isJust binaryField && getMediaType mt == MTTextXML = asXmlF $ fromJust binaryField
| isJust binaryField = asBinaryF $ fromJust binaryField
| otherwise = asJsonF False
| otherwise = asJsonF False False False
decodeIt :: HD.Result ResultSet
decodeIt = case mt of
MTPlan{} -> planRow
_ -> HD.singleRow $ standardRow True
prepareCall :: Bool -> Bool -> SQL.Snippet -> SQL.Snippet -> SQL.Snippet -> Bool ->
prepareCall :: Bool -> Bool -> Bool -> SQL.Snippet -> SQL.Snippet -> SQL.Snippet -> Bool ->
MediaType -> Maybe FieldName -> Bool ->
SQL.Statement () ResultSet
prepareCall returnsScalar returnsSingle callProcQuery selectQuery countQuery countTotal mt binaryField =
prepareCall returnsScalar returnsSingleComposite returnsSetOfScalar callProcQuery selectQuery countQuery countTotal mt binaryField =
SQL.dynamicallyParameterized (mtSnippet mt snippet) decodeIt
where
snippet =
@@ -156,8 +156,7 @@ prepareCall returnsScalar returnsSingle callProcQuery selectQuery countQuery cou
| getMediaType mt == MTGeoJSON = asGeoJsonF
| isJust binaryField && getMediaType mt == MTTextXML = asXmlF $ fromJust binaryField
| isJust binaryField = asBinaryF $ fromJust binaryField
| returnsSingle = asJsonSingleF returnsScalar
| otherwise = asJsonF returnsScalar
| otherwise = asJsonF returnsScalar returnsSetOfScalar returnsSingleComposite
decodeIt :: HD.Result ResultSet
decodeIt = case mt of
+14 -9
View File
@@ -9,7 +9,8 @@ module PostgREST.SchemaCache.Proc
, ProcsMap
, RetType(..)
, procReturnsScalar
, procReturnsSingle
, procReturnsSetOfScalar
, procReturnsSingleComposite
, procReturnsVoid
, procTableName
) where
@@ -71,21 +72,25 @@ type ProcsMap = HM.HashMap QualifiedIdentifier [ProcDescription]
procReturnsScalar :: ProcDescription -> Bool
procReturnsScalar proc = case proc of
ProcDescription{pdReturnType = Single (Scalar _)} -> True
ProcDescription{pdReturnType = SetOf (Scalar _)} -> True
_ -> False
_ -> False
procReturnsSingle :: ProcDescription -> Bool
procReturnsSingle proc = case proc of
ProcDescription{pdReturnType = Single _} -> True
_ -> False
procReturnsSetOfScalar :: ProcDescription -> Bool
procReturnsSetOfScalar proc = case proc of
ProcDescription{pdReturnType = SetOf (Scalar _)} -> 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
_ -> False
procTableName :: ProcDescription -> Maybe TableName
procTableName proc = case pdReturnType proc of
SetOf (Composite qi) -> Just $ qiName qi
Single (Composite qi) -> Just $ qiName qi
_ -> Nothing
_ -> Nothing