diff options
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 125 |
1 files changed, 38 insertions, 87 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index f936710171c..25f2c5a6147 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -490,6 +490,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, root->processed_tlist = NIL; root->grouping_map = NULL; root->minmax_aggs = NIL; + root->qual_security_level = 0; root->hasInheritedTarget = false; root->hasRecursion = hasRecursion; if (hasRecursion) @@ -669,6 +670,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, { RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); int kind; + ListCell *lcsq; if (rte->rtekind == RTE_RELATION) { @@ -704,6 +706,19 @@ subquery_planner(PlannerGlobal *glob, Query *parse, rte->values_lists = (List *) preprocess_expression(root, (Node *) rte->values_lists, kind); } + + /* + * Process each element of the securityQuals list as if it were a + * separate qual expression (as indeed it is). We need to do it this + * way to get proper canonicalization of AND/OR structure. Note that + * this converts each element into an implicit-AND sublist. + */ + foreach(lcsq, rte->securityQuals) + { + lfirst(lcsq) = preprocess_expression(root, + (Node *) lfirst(lcsq), + EXPRKIND_QUAL); + } } /* @@ -978,7 +993,6 @@ inheritance_planner(PlannerInfo *root) { Query *parse = root->parse; int parentRTindex = parse->resultRelation; - Bitmapset *resultRTindexes; Bitmapset *subqueryRTindexes; Bitmapset *modifiableARIindexes; int nominalRelation = -1; @@ -1012,26 +1026,7 @@ inheritance_planner(PlannerInfo *root) * at least O(N^3) work expended here; and (2) would greatly complicate * management of the rowMarks list. * - * Note that any RTEs with security barrier quals will be turned into - * subqueries during planning, and so we must create copies of them too, - * except where they are target relations, which will each only be used in - * a single plan. - * - * To begin with, we'll need a bitmapset of the target relation relids. - */ - resultRTindexes = bms_make_singleton(parentRTindex); - foreach(lc, root->append_rel_list) - { - AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc); - - if (appinfo->parent_relid == parentRTindex) - resultRTindexes = bms_add_member(resultRTindexes, - appinfo->child_relid); - } - - /* - * Now, generate a bitmapset of the relids of the subquery RTEs, including - * security-barrier RTEs that will become subqueries, as just explained. + * To begin with, generate a bitmapset of the relids of the subquery RTEs. */ subqueryRTindexes = NULL; rti = 1; @@ -1039,9 +1034,7 @@ inheritance_planner(PlannerInfo *root) { RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); - if (rte->rtekind == RTE_SUBQUERY || - (rte->securityQuals != NIL && - !bms_is_member(rti, resultRTindexes))) + if (rte->rtekind == RTE_SUBQUERY) subqueryRTindexes = bms_add_member(subqueryRTindexes, rti); rti++; } @@ -1079,6 +1072,8 @@ inheritance_planner(PlannerInfo *root) { AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc); PlannerInfo *subroot; + RangeTblEntry *parent_rte; + RangeTblEntry *child_rte; RelOptInfo *sub_final_rel; Path *subpath; @@ -1105,6 +1100,15 @@ inheritance_planner(PlannerInfo *root) appinfo); /* + * If there are securityQuals attached to the parent, move them to the + * child rel (they've already been transformed properly for that). + */ + parent_rte = rt_fetch(parentRTindex, subroot->parse->rtable); + child_rte = rt_fetch(appinfo->child_relid, subroot->parse->rtable); + child_rte->securityQuals = parent_rte->securityQuals; + parent_rte->securityQuals = NIL; + + /* * The rowMarks list might contain references to subquery RTEs, so * make a copy that we can apply ChangeVarNodes to. (Fortunately, the * executor doesn't need to see the modified copies --- we can just @@ -1151,11 +1155,11 @@ inheritance_planner(PlannerInfo *root) /* * If this isn't the first child Query, generate duplicates of all - * subquery (or subquery-to-be) RTEs, and adjust Var numbering to - * reference the duplicates. To simplify the loop logic, we scan the - * original rtable not the copy just made by adjust_appendrel_attrs; - * that should be OK since subquery RTEs couldn't contain any - * references to the target rel. + * subquery RTEs, and adjust Var numbering to reference the + * duplicates. To simplify the loop logic, we scan the original rtable + * not the copy just made by adjust_appendrel_attrs; that should be OK + * since subquery RTEs couldn't contain any references to the target + * rel. */ if (final_rtable != NIL && subqueryRTindexes != NULL) { @@ -1172,9 +1176,9 @@ inheritance_planner(PlannerInfo *root) /* * The RTE can't contain any references to its own RT - * index, except in the security barrier quals, so we can - * save a few cycles by applying ChangeVarNodes before we - * append the RTE to the rangetable. + * index, except in its securityQuals, so we can save a + * few cycles by applying ChangeVarNodes to the rest of + * the rangetable before we append the RTE to it. */ newrti = list_length(subroot->parse->rtable) + 1; ChangeVarNodes((Node *) subroot->parse, rti, newrti, 0); @@ -1213,12 +1217,6 @@ inheritance_planner(PlannerInfo *root) grouping_planner(subroot, true, 0.0 /* retrieve all tuples */ ); /* - * Planning may have modified the query result relation (if there were - * security barrier quals on the result RTE). - */ - appinfo->child_relid = subroot->parse->resultRelation; - - /* * We'll use the first child relation (even if it's excluded) as the * nominal target relation of the ModifyTable node. Because of the * way expand_inherited_rtentry works, this should always be the RTE @@ -1256,41 +1254,9 @@ inheritance_planner(PlannerInfo *root) if (final_rtable == NIL) final_rtable = subroot->parse->rtable; else - { - List *tmp_rtable = NIL; - ListCell *cell1, - *cell2; - - /* - * Check to see if any of the original RTEs were turned into - * subqueries during planning. Currently, this should only ever - * happen due to securityQuals being involved which push a - * relation down under a subquery, to ensure that the security - * barrier quals are evaluated first. - * - * When this happens, we want to use the new subqueries in the - * final rtable. - */ - forboth(cell1, final_rtable, cell2, subroot->parse->rtable) - { - RangeTblEntry *rte1 = (RangeTblEntry *) lfirst(cell1); - RangeTblEntry *rte2 = (RangeTblEntry *) lfirst(cell2); - - if (rte1->rtekind == RTE_RELATION && - rte2->rtekind == RTE_SUBQUERY) - { - /* Should only be when there are securityQuals today */ - Assert(rte1->securityQuals != NIL); - tmp_rtable = lappend(tmp_rtable, rte2); - } - else - tmp_rtable = lappend(tmp_rtable, rte1); - } - - final_rtable = list_concat(tmp_rtable, + final_rtable = list_concat(final_rtable, list_copy_tail(subroot->parse->rtable, list_length(final_rtable))); - } /* * We need to collect all the RelOptInfos from all child plans into @@ -1635,12 +1601,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, parse->rtable); /* - * Expand any rangetable entries that have security barrier quals. - * This may add new security barrier subquery RTEs to the rangetable. - */ - expand_security_quals(root, tlist); - - /* * We are now done hacking up the query's targetlist. Most of the * remaining planning work will be done with the PathTarget * representation of tlists, but save aside the full representation so @@ -2297,17 +2257,8 @@ select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength) /* * We don't need a tuple lock, only the ability to re-fetch - * the row. Regular tables support ROW_MARK_REFERENCE, but if - * this RTE has security barrier quals, it will be turned into - * a subquery during planning, so use ROW_MARK_COPY. - * - * This is only necessary for LCS_NONE, since real tuple locks - * on an RTE with security barrier quals are supported by - * pushing the lock down into the subquery --- see - * expand_security_qual. + * the row. */ - if (rte->securityQuals != NIL) - return ROW_MARK_COPY; return ROW_MARK_REFERENCE; break; case LCS_FORKEYSHARE: |