1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Make RLS work with UPDATE ... WHERE CURRENT OF

UPDATE ... WHERE CURRENT OF would not work in conjunction with
RLS. Arrange to allow the CURRENT OF expression to be pushed down.
Issue noted by Peter Geoghegan. Patch by Dean Rasheed. Back patch
to 9.5 where RLS was introduced.
This commit is contained in:
Joe Conway
2015-07-24 12:56:25 -07:00
parent 016f28ad3d
commit 7d4240d6cd
4 changed files with 206 additions and 0 deletions

View File

@@ -2177,6 +2177,46 @@ subquery_push_qual(Query *subquery, RangeTblEntry *rte, Index rti, Node *qual)
recurse_push_qual(subquery->setOperations, subquery,
rte, rti, qual);
}
else if (IsA(qual, CurrentOfExpr))
{
/*
* This is possible when a WHERE CURRENT OF expression is applied to a
* table with row-level security. In that case, the subquery should
* contain precisely one rtable entry for the table, and we can safely
* push the expression down into the subquery. This will cause a TID
* scan subquery plan to be generated allowing the target relation to
* be updated.
*
* Someday we might also be able to use a WHERE CURRENT OF expression
* on a view, but currently the rewriter prevents that, so we should
* never see any other case here, but generate sane error messages in
* case it does somehow happen.
*/
if (subquery->rtable == NIL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WHERE CURRENT OF is not supported on a view with no underlying relation")));
if (list_length(subquery->rtable) > 1)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WHERE CURRENT OF is not supported on a view with more than one underlying relation")));
if (subquery->hasAggs || subquery->groupClause || subquery->groupingSets || subquery->havingQual)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("WHERE CURRENT OF is not supported on a view with grouping or aggregation")));
/*
* Adjust the CURRENT OF expression to refer to the underlying table
* in the subquery, and attach it to the subquery's WHERE clause.
*/
qual = copyObject(qual);
((CurrentOfExpr *) qual)->cvarno = 1;
subquery->jointree->quals =
make_and_qual(subquery->jointree->quals, qual);
}
else
{
/*

View File

@@ -1492,6 +1492,16 @@ contain_leaked_vars_walker(Node *node, void *context)
}
break;
case T_CurrentOfExpr:
/*
* WHERE CURRENT OF doesn't contain function calls. Moreover, it
* is important that this can be pushed down into a
* security_barrier view, since the planner must always generate
* a TID scan when CURRENT OF is present -- c.f. cost_tidscan.
*/
return false;
default:
/*