aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r--src/backend/optimizer/plan/planner.c6
-rw-r--r--src/backend/optimizer/plan/setrefs.c73
-rw-r--r--src/backend/optimizer/plan/subselect.c8
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.