diff options
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 106 |
1 files changed, 75 insertions, 31 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index cb65c0502ef..e640c1eaa51 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -25,6 +25,7 @@ #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteHandler.h" #include "rewrite/rewriteManip.h" +#include "rewrite/rowsecurity.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/rel.h" @@ -1670,48 +1671,91 @@ fireRIRrules(Query *parsetree, List *activeRIRs, bool forUpdatePushedDown) * Collect the RIR rules that we must apply */ rules = rel->rd_rules; - if (rules == NULL) + if (rules != NULL) { - heap_close(rel, NoLock); - continue; - } - locks = NIL; - for (i = 0; i < rules->numLocks; i++) - { - rule = rules->rules[i]; - if (rule->event != CMD_SELECT) - continue; + locks = NIL; + for (i = 0; i < rules->numLocks; i++) + { + rule = rules->rules[i]; + if (rule->event != CMD_SELECT) + continue; - locks = lappend(locks, rule); - } + locks = lappend(locks, rule); + } + + /* + * If we found any, apply them --- but first check for recursion! + */ + if (locks != NIL) + { + ListCell *l; + + if (list_member_oid(activeRIRs, RelationGetRelid(rel))) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("infinite recursion detected in rules for relation \"%s\"", + RelationGetRelationName(rel)))); + activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs); + + foreach(l, locks) + { + rule = lfirst(l); + + parsetree = ApplyRetrieveRule(parsetree, + rule, + rt_index, + rel, + activeRIRs, + forUpdatePushedDown); + } + activeRIRs = list_delete_first(activeRIRs); + } + } /* - * If we found any, apply them --- but first check for recursion! + * If the RTE has row-security quals, apply them and recurse into the + * securityQuals. */ - if (locks != NIL) + if (prepend_row_security_policies(parsetree, rte, rt_index)) { - ListCell *l; - + /* + * We applied security quals, check for infinite recursion and + * then expand any nested queries. + */ if (list_member_oid(activeRIRs, RelationGetRelid(rel))) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("infinite recursion detected in rules for relation \"%s\"", - RelationGetRelationName(rel)))); - activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs); + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("infinite recursion detected in row-security policy for relation \"%s\"", + RelationGetRelationName(rel)))); + + /* + * Make sure we check for recursion in either securityQuals or + * WITH CHECK quals. + */ + if (rte->securityQuals != NIL) + { + activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs); - foreach(l, locks) + expression_tree_walker( (Node*) rte->securityQuals, + fireRIRonSubLink, (void*)activeRIRs ); + + activeRIRs = list_delete_first(activeRIRs); + } + + if (parsetree->withCheckOptions != NIL) { - rule = lfirst(l); - - parsetree = ApplyRetrieveRule(parsetree, - rule, - rt_index, - rel, - activeRIRs, - forUpdatePushedDown); + WithCheckOption *wco; + List *quals = NIL; + + wco = (WithCheckOption *) makeNode(WithCheckOption); + quals = lcons(wco->qual, quals); + + activeRIRs = lcons_oid(RelationGetRelid(rel), activeRIRs); + + expression_tree_walker( (Node*) quals, fireRIRonSubLink, + (void*)activeRIRs); } - activeRIRs = list_delete_first(activeRIRs); } heap_close(rel, NoLock); |