Location header improvements(#1475)
* Create location header only on primary key columns, closes https://github.com/PostgREST/postgrest/issues/1461 * Return location header when pk columns not selected, fixes https://github.com/PostgREST/postgrest/issues/1162
This commit is contained in:
@@ -361,7 +361,7 @@ app dbStructure proc cols conf apiRequest =
|
||||
let
|
||||
readReq = readRequest s t maxRows (dbRelations dbStructure) apiRequest
|
||||
returnings :: ReadRequest -> Either Response [FieldName]
|
||||
returnings rr = Right (returningCols rr)
|
||||
returnings rr = Right (returningCols rr [])
|
||||
in
|
||||
(,,,) <$>
|
||||
(readRequestToQuery <$> readReq) <*>
|
||||
|
||||
@@ -316,7 +316,7 @@ mutateRequest schema tName apiRequest cols pkCols readReq = mapLeft errorRespons
|
||||
returnings =
|
||||
if iPreferRepresentation apiRequest == None
|
||||
then []
|
||||
else returningCols readReq
|
||||
else returningCols readReq pkCols
|
||||
filters = map snd <$> mapM pRequestFilter mutateFilters
|
||||
logic = map snd <$> mapM pRequestLogicTree logicFilters
|
||||
combinedLogic = foldr addFilterToLogicForest <$> logic <*> filters
|
||||
@@ -324,8 +324,11 @@ mutateRequest schema tName apiRequest cols pkCols readReq = mapLeft errorRespons
|
||||
(mutateFilters, logicFilters) = join (***) onlyRoot (iFilters apiRequest, iLogic apiRequest)
|
||||
onlyRoot = filter (not . ( "." `isInfixOf` ) . fst)
|
||||
|
||||
returningCols :: ReadRequest -> [FieldName]
|
||||
returningCols rr@(Node _ forest) = returnings
|
||||
returningCols :: ReadRequest -> [FieldName] -> [FieldName]
|
||||
returningCols rr@(Node _ forest) pkCols
|
||||
-- if * is part of the select, we must not add pk or fk columns manually - otherwise those would be selected and output twice
|
||||
| "*" `elem` fldNames = ["*"]
|
||||
| otherwise = returnings
|
||||
where
|
||||
fldNames = fstFieldNames rr
|
||||
-- Without fkCols, when a mutateRequest to /projects?select=name,clients(name) occurs, the RETURNING SQL part would be
|
||||
@@ -343,7 +346,8 @@ returningCols rr@(Node _ forest) = returnings
|
||||
-- However if the "client_id" is present, e.g. mutateRequest to /projects?select=client_id,name,clients(name)
|
||||
-- we would get `RETURNING client_id, name, client_id` and then we would produce the "column reference \"client_id\" is ambiguous"
|
||||
-- error from PostgreSQL. So we deduplicate with Set:
|
||||
returnings = S.toList . S.fromList $ fldNames ++ (colName <$> fkCols)
|
||||
-- We are adding the primary key columns as well to make sure, that a proper location header can always be built for INSERT/POST
|
||||
returnings = S.toList . S.fromList $ fldNames ++ (colName <$> fkCols) ++ pkCols
|
||||
|
||||
-- Traditional filters(e.g. id=eq.1) are added as root nodes of the LogicTree
|
||||
-- they are later concatenated with AND in the QueryBuilder
|
||||
|
||||
@@ -87,10 +87,12 @@ asBinaryF fieldName = "coalesce(string_agg(_postgrest_t." <> pgFmtIdent fieldNam
|
||||
locationF :: [Text] -> SqlFragment
|
||||
locationF pKeys = [qc|(
|
||||
WITH data AS (SELECT row_to_json(_) AS row FROM {sourceCTEName} AS _ LIMIT 1)
|
||||
SELECT array_agg(json_data.key || '=' || coalesce('eq.' || json_data.value, 'is.null'))
|
||||
SELECT array_agg(json_data.key || '=eq.' || json_data.value)
|
||||
FROM data CROSS JOIN json_each_text(data.row) AS json_data
|
||||
{("WHERE json_data.key IN ('" <> intercalate "','" pKeys <> "')") `emptyOnFalse` null pKeys}
|
||||
WHERE json_data.key IN ('{fmtPKeys}')
|
||||
)|]
|
||||
where
|
||||
fmtPKeys = intercalate "','" pKeys
|
||||
|
||||
fromQi :: QualifiedIdentifier -> SqlFragment
|
||||
fromQi t = (if s == "" then "" else pgFmtIdent s <> ".") <> pgFmtIdent n
|
||||
|
||||
Reference in New Issue
Block a user