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