diff options
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 6 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 73 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 8 |
3 files changed, 70 insertions, 17 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 799602f5ea5..15aa9c50876 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -57,6 +57,7 @@ #include "optimizer/tlist.h" #include "parser/analyze.h" #include "parser/parse_agg.h" +#include "parser/parse_relation.h" #include "parser/parsetree.h" #include "partitioning/partdesc.h" #include "rewrite/rewriteManip.h" @@ -306,6 +307,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, glob->subroots = NIL; glob->rewindPlanIDs = NULL; glob->finalrtable = NIL; + glob->finalrteperminfos = NIL; glob->finalrowmarks = NIL; glob->resultRelations = NIL; glob->appendRelations = NIL; @@ -493,6 +495,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, /* final cleanup of the plan */ Assert(glob->finalrtable == NIL); + Assert(glob->finalrteperminfos == NIL); Assert(glob->finalrowmarks == NIL); Assert(glob->resultRelations == NIL); Assert(glob->appendRelations == NIL); @@ -521,6 +524,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, result->planTree = top_plan; result->partPruneInfos = glob->partPruneInfos; result->rtable = glob->finalrtable; + result->permInfos = glob->finalrteperminfos; result->resultRelations = glob->resultRelations; result->appendRelations = glob->appendRelations; result->subplans = glob->subplans; @@ -6266,6 +6270,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid) rte->inh = false; rte->inFromCl = true; query->rtable = list_make1(rte); + addRTEPermissionInfo(&query->rteperminfos, rte); /* Set up RTE/RelOptInfo arrays */ setup_simple_rel_arrays(root); @@ -6393,6 +6398,7 @@ plan_create_index_workers(Oid tableOid, Oid indexOid) rte->inh = true; rte->inFromCl = true; query->rtable = list_make1(rte); + addRTEPermissionInfo(&query->rteperminfos, rte); /* Set up RTE/RelOptInfo arrays */ setup_simple_rel_arrays(root); diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 399c1812d40..596f1fbc8e5 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -24,6 +24,7 @@ #include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/tlist.h" +#include "parser/parse_relation.h" #include "tcop/utility.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -78,6 +79,13 @@ typedef struct int newvarno; } fix_windowagg_cond_context; +/* Context info for flatten_rtes_walker() */ +typedef struct +{ + PlannerGlobal *glob; + Query *query; +} flatten_rtes_walker_context; + /* * Selecting the best alternative in an AlternativeSubPlan expression requires * estimating how many times that expression will be evaluated. For an @@ -113,8 +121,9 @@ typedef struct static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing); static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte); -static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob); -static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte); +static bool flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt); +static void add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos, + RangeTblEntry *rte); static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset); static Plan *set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, @@ -380,6 +389,9 @@ set_plan_references(PlannerInfo *root, Plan *plan) * Extract RangeTblEntries from the plan's rangetable, and add to flat rtable * * This can recurse into subquery plans; "recursing" is true if so. + * + * This also seems like a good place to add the query's RTEPermissionInfos to + * the flat rteperminfos. */ static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing) @@ -400,7 +412,7 @@ add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing) RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); if (!recursing || rte->rtekind == RTE_RELATION) - add_rte_to_flat_rtable(glob, rte); + add_rte_to_flat_rtable(glob, root->parse->rteperminfos, rte); } /* @@ -467,18 +479,21 @@ add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing) /* * Extract RangeTblEntries from a subquery that was never planned at all */ + static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte) { + flatten_rtes_walker_context cxt = {glob, rte->subquery}; + /* Use query_tree_walker to find all RTEs in the parse tree */ (void) query_tree_walker(rte->subquery, flatten_rtes_walker, - (void *) glob, + (void *) &cxt, QTW_EXAMINE_RTES_BEFORE); } static bool -flatten_rtes_walker(Node *node, PlannerGlobal *glob) +flatten_rtes_walker(Node *node, flatten_rtes_walker_context *cxt) { if (node == NULL) return false; @@ -488,33 +503,38 @@ flatten_rtes_walker(Node *node, PlannerGlobal *glob) /* As above, we need only save relation RTEs */ if (rte->rtekind == RTE_RELATION) - add_rte_to_flat_rtable(glob, rte); + add_rte_to_flat_rtable(cxt->glob, cxt->query->rteperminfos, rte); return false; } if (IsA(node, Query)) { - /* Recurse into subselects */ + /* + * Recurse into subselects. Must update cxt->query to this query so + * that the rtable and rteperminfos correspond with each other. + */ + cxt->query = (Query *) node; return query_tree_walker((Query *) node, flatten_rtes_walker, - (void *) glob, + (void *) cxt, QTW_EXAMINE_RTES_BEFORE); } return expression_tree_walker(node, flatten_rtes_walker, - (void *) glob); + (void *) cxt); } /* - * Add (a copy of) the given RTE to the final rangetable + * Add (a copy of) the given RTE to the final rangetable and also the + * corresponding RTEPermissionInfo, if any, to final rteperminfos. * * In the flat rangetable, we zero out substructure pointers that are not * needed by the executor; this reduces the storage space and copying cost - * for cached plans. We keep only the ctename, alias and eref Alias fields, - * which are needed by EXPLAIN, and the selectedCols, insertedCols, - * updatedCols, and extraUpdatedCols bitmaps, which are needed for - * executor-startup permissions checking and for trigger event checking. + * for cached plans. We keep only the ctename, alias, eref Alias fields, + * which are needed by EXPLAIN, and perminfoindex which is needed by the + * executor to fetch the RTE's RTEPermissionInfo. */ static void -add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte) +add_rte_to_flat_rtable(PlannerGlobal *glob, List *rteperminfos, + RangeTblEntry *rte) { RangeTblEntry *newrte; @@ -552,6 +572,29 @@ add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte) */ if (newrte->rtekind == RTE_RELATION) glob->relationOids = lappend_oid(glob->relationOids, newrte->relid); + + /* + * Add a copy of the RTEPermissionInfo, if any, corresponding to this RTE + * to the flattened global list. + */ + if (rte->perminfoindex > 0) + { + RTEPermissionInfo *perminfo; + RTEPermissionInfo *newperminfo; + + /* Get the existing one from this query's rteperminfos. */ + perminfo = getRTEPermissionInfo(rteperminfos, newrte); + + /* + * Add a new one to finalrteperminfos and copy the contents of the + * existing one into it. Note that addRTEPermissionInfo() also + * updates newrte->perminfoindex to point to newperminfo in + * finalrteperminfos. + */ + newrte->perminfoindex = 0; /* expected by addRTEPermissionInfo() */ + newperminfo = addRTEPermissionInfo(&glob->finalrteperminfos, newrte); + memcpy(newperminfo, perminfo, sizeof(RTEPermissionInfo)); + } } /* diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 92e33385842..abd407825b5 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -1496,8 +1496,12 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, if (!bms_is_subset(upper_varnos, available_rels)) return NULL; - /* Now we can attach the modified subquery rtable to the parent */ - parse->rtable = list_concat(parse->rtable, subselect->rtable); + /* + * Now we can attach the modified subquery rtable to the parent. This also + * adds subquery's RTEPermissionInfos into the upper query. + */ + CombineRangeTables(&parse->rtable, &parse->rteperminfos, + subselect->rtable, subselect->rteperminfos); /* * And finally, build the JoinExpr node. |