Fix overloaded computed columns on RPC (#1473)

* fix some typos and spelling

* fix pg_source CTE name should be prefixed with pgrst_

* added tests for overloaded computed columns on patch calls
This commit is contained in:
Wolfgang Walther
2020-04-06 14:04:55 -05:00
committed by GitHub
parent 82fa1d8812
commit c524531784
14 changed files with 184 additions and 78 deletions
+10 -6
View File
@@ -46,7 +46,8 @@ import PostgREST.ApiRequest (Action (..), ApiRequest (..),
import PostgREST.Auth (containsRole, jwtClaims,
parseSecret)
import PostgREST.Config (AppConfig (..))
import PostgREST.DbRequestBuilder (mutateRequest, readRequest)
import PostgREST.DbRequestBuilder (mutateRequest, readRequest,
returningCols)
import PostgREST.DbStructure
import PostgREST.Error (PgError (..), SimpleError (..),
errorResponseFor, singularityError)
@@ -127,7 +128,7 @@ app dbStructure proc cols conf apiRequest =
(ActionRead headersOnly, TargetIdent (QualifiedIdentifier tSchema tName), Nothing) ->
case readSqlParts tSchema tName of
Left errorResponse -> return errorResponse
Right (q, cq, bField) -> do
Right (q, cq, bField, _) -> do
let cQuery = if estimatedCount
then limitedQuery cq ((+ 1) <$> maxRows) -- LIMIT maxRows + 1 so we can determine below that maxRows was surpassed
else cq
@@ -293,10 +294,10 @@ app dbStructure proc cols conf apiRequest =
let tName = fromMaybe pName $ procTableName =<< proc in
case readSqlParts tSchema tName of
Left errorResponse -> return errorResponse
Right (q, cq, bField) -> do
Right (q, cq, bField, returning) -> do
let
preferParams = iPreferParameters apiRequest
pq = requestToCallProcQuery qi (specifiedProcArgs cols proc) returnsScalar preferParams
pq = requestToCallProcQuery qi (specifiedProcArgs cols proc) returnsScalar preferParams returning
stm = callProcStatement returnsScalar pq q cq shouldCount (contentType == CTSingularJSON)
(contentType == CTTextCSV) (contentType `elem` rawContentTypes) (preferParams == Just MultipleObjects)
bField pgVer
@@ -351,11 +352,14 @@ app dbStructure proc cols conf apiRequest =
readSqlParts s t =
let
readReq = readRequest s t maxRows (dbRelations dbStructure) apiRequest
returnings :: ReadRequest -> Either Response [FieldName]
returnings rr = Right (returningCols rr)
in
(,,) <$>
(,,,) <$>
(readRequestToQuery <$> readReq) <*>
(readRequestToCountQuery <$> readReq) <*>
(binaryField contentType rawContentTypes returnsScalar =<< readReq)
(binaryField contentType rawContentTypes returnsScalar =<< readReq) <*>
(returnings =<< readReq)
mutateSqlParts s t =
let
+4 -3
View File
@@ -14,6 +14,7 @@ A query tree is built in case of resource embedding. By inferring the relationsh
module PostgREST.DbRequestBuilder (
readRequest
, mutateRequest
, returningCols
) where
import qualified Data.HashMap.Strict as M
@@ -40,7 +41,7 @@ readRequest :: Schema -> TableName -> Maybe Integer -> [Relation] -> ApiRequest
readRequest schema rootTableName maxRows allRels apiRequest =
mapLeft errorResponseFor $
treeRestrictRange maxRows =<<
augumentRequestWithJoin schema rootRels =<<
augmentRequestWithJoin schema rootRels =<<
addFiltersOrdersRanges apiRequest <*>
(initReadRequest rootName <$> pRequestSelect sel)
where
@@ -89,8 +90,8 @@ treeRestrictRange maxRows request = pure $ nodeRestrictRange maxRows <$> request
nodeRestrictRange :: Maybe Integer -> ReadNode -> ReadNode
nodeRestrictRange m (q@Select {range_=r}, i) = (q{range_=restrictRange m r }, i)
augumentRequestWithJoin :: Schema -> [Relation] -> ReadRequest -> Either ApiRequestError ReadRequest
augumentRequestWithJoin schema allRels request =
augmentRequestWithJoin :: Schema -> [Relation] -> ReadRequest -> Either ApiRequestError ReadRequest
augmentRequestWithJoin schema allRels request =
addRels schema allRels Nothing request
>>= addJoinConditions Nothing
+2 -2
View File
@@ -186,8 +186,8 @@ countF :: SqlQuery -> Bool -> (SqlFragment, SqlFragment)
countF countQuery shouldCount =
if shouldCount
then (
", pg_source_count AS (" <> countQuery <> ")"
, "(SELECT pg_catalog.count(*) FROM pg_source_count)" )
", pgrst_source_count AS (" <> countQuery <> ")"
, "(SELECT pg_catalog.count(*) FROM pgrst_source_count)" )
else (
mempty
, "null::bigint")
+12 -7
View File
@@ -113,15 +113,15 @@ mutateRequestToQuery (Delete mainQi logicForest returnings) =
returningF mainQi returnings
]
requestToCallProcQuery :: QualifiedIdentifier -> [PgArg] -> Bool -> Maybe PreferParameters -> SqlQuery
requestToCallProcQuery qi pgArgs returnsScalar preferParams =
requestToCallProcQuery :: QualifiedIdentifier -> [PgArg] -> Bool -> Maybe PreferParameters -> [FieldName] -> SqlQuery
requestToCallProcQuery qi pgArgs returnsScalar preferParams returnings =
unwords [
"WITH",
argsCTE,
sourceBody ]
where
paramsAsSingleObject = preferParams == Just SingleObject
paramsAsMulitpleObjects = preferParams == Just MultipleObjects
paramsAsMultipleObjects = preferParams == Just MultipleObjects
(argsCTE, args)
| null pgArgs = (ignoredBody, "")
@@ -132,7 +132,7 @@ requestToCallProcQuery qi pgArgs returnsScalar preferParams =
"pgrst_args AS (",
"SELECT * FROM json_to_recordset(" <> selectBody <> ") AS _(" <> fmtArgs (\a -> " " <> pgaType a) <> ")",
")"]
, if paramsAsMulitpleObjects
, if paramsAsMultipleObjects
then fmtArgs (\a -> " := pgrst_args." <> pgFmtIdent (pgaName a))
else fmtArgs (\a -> " := (SELECT " <> pgFmtIdent (pgaName a) <> " FROM pgrst_args LIMIT 1)")
)
@@ -142,20 +142,25 @@ requestToCallProcQuery qi pgArgs returnsScalar preferParams =
sourceBody :: SqlFragment
sourceBody
| paramsAsMulitpleObjects =
| paramsAsMultipleObjects =
if returnsScalar
then "SELECT " <> callIt <> " AS pgrst_scalar FROM pgrst_args"
else unwords [ "SELECT pgrst_lat_args.*"
, "FROM pgrst_args,"
, "LATERAL ( SELECT * FROM " <> callIt <> " ) pgrst_lat_args" ]
, "LATERAL ( SELECT " <> returned_columns <> " FROM " <> callIt <> " ) pgrst_lat_args" ]
| otherwise =
if returnsScalar
then "SELECT " <> callIt <> " AS pgrst_scalar"
else "SELECT * FROM " <> callIt
else "SELECT " <> returned_columns <> " FROM " <> callIt
callIt :: SqlFragment
callIt = fromQi qi <> "(" <> args <> ")"
returned_columns :: SqlFragment
returned_columns
| null returnings = "*"
| otherwise = intercalate ", " (pgFmtColumn (QualifiedIdentifier mempty $ qiName qi) <$> returnings)
-- | SQL query meant for COUNTing the root node of the Tree.
-- It only takes WHERE into account and doesn't include LIMIT/OFFSET because it would reduce the COUNT.
+1 -1
View File
@@ -522,7 +522,7 @@ pgVersion121 :: PgVersion
pgVersion121 = PgVersion 120001 "12.1"
sourceCTEName :: SqlFragment
sourceCTEName = "pg_source"
sourceCTEName = "pgrst_source"
-- | full jspath, e.g. .property[0].attr.detail
type JSPath = [JSPathExp]