Repair rule permissions-checking bug reported by Tim Burgess 10-Feb-02:
authorTom Lane <[email protected]>
Thu, 13 Feb 2003 21:40:00 +0000 (21:40 +0000)
committerTom Lane <[email protected]>
Thu, 13 Feb 2003 21:40:00 +0000 (21:40 +0000)
the table(s) modified by the original query would get checked for the
type of write permission needed by a rule query.

src/backend/rewrite/rewriteHandler.c

index f8b63b72c2fe9ad1029cf2d81500aee0ec2d3d20..3f643c43e969fd6922634295e347ea0582080e29 100644 (file)
@@ -62,9 +62,11 @@ rewriteRuleAction(Query *parsetree,
 {
        int                     current_varno,
                                new_varno;
+       List       *main_rtable;
        int                     rt_length;
        Query      *sub_action;
        Query     **sub_action_ptr;
+       List       *rt;
 
        /*
         * Make modifiable copies of rule action and qual (what we're passed
@@ -99,16 +101,31 @@ rewriteRuleAction(Query *parsetree,
         * Generate expanded rtable consisting of main parsetree's rtable plus
         * rule action's rtable; this becomes the complete rtable for the rule
         * action.      Some of the entries may be unused after we finish
-        * rewriting, but if we tried to clean those out we'd have a much
+        * rewriting, but if we tried to remove them we'd have a much
         * harder job to adjust RT indexes in the query's Vars.  It's OK to
         * have unused RT entries, since planner will ignore them.
         *
         * NOTE: because planner will destructively alter rtable, we must ensure
         * that rule action's rtable is separate and shares no substructure
         * with the main rtable.  Hence do a deep copy here.
+        *
+        * Also, we must disable write-access checking in all the RT entries
+        * copied from the main query.  This is safe since in fact the rule action
+        * won't write on them, and it's necessary because the rule action may
+        * have a different commandType than the main query, causing
+        * ExecCheckRTEPerms() to make an inappropriate check.  The read-access
+        * checks can be left enabled, although they're probably redundant.
         */
-       sub_action->rtable = nconc((List *) copyObject(parsetree->rtable),
-                                                          sub_action->rtable);
+       main_rtable = (List *) copyObject(parsetree->rtable);
+
+       foreach(rt, main_rtable)
+       {
+               RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
+
+               rte->checkForWrite = false;
+       }
+
+       sub_action->rtable = nconc(main_rtable, sub_action->rtable);
 
        /*
         * Each rule action's jointree should be the main parsetree's jointree