diff options
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 6ceb80192e1..c170e9614f6 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -51,6 +51,9 @@ static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, Relids *qualscope, Relids *inner_join_rels, List **postponed_qual_list); +static void process_security_barrier_quals(PlannerInfo *root, + int rti, Relids qualscope, + bool below_outer_join); static SpecialJoinInfo *make_outerjoininfo(PlannerInfo *root, Relids left_rels, Relids right_rels, Relids inner_join_rels, @@ -60,6 +63,7 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_deduced, bool below_outer_join, JoinType jointype, + Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, @@ -745,8 +749,14 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { int varno = ((RangeTblRef *) jtnode)->rtindex; - /* No quals to deal with, just return correct result */ + /* qualscope is just the one RTE */ *qualscope = bms_make_singleton(varno); + /* Deal with any securityQuals attached to the RTE */ + if (root->qual_security_level > 0) + process_security_barrier_quals(root, + varno, + *qualscope, + below_outer_join); /* A single baserel does not create an inner join */ *inner_join_rels = NULL; joinlist = list_make1(jtnode); @@ -810,6 +820,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, if (bms_is_subset(pq->relids, *qualscope)) distribute_qual_to_rels(root, pq->qual, false, below_outer_join, JOIN_INNER, + root->qual_security_level, *qualscope, NULL, NULL, NULL, NULL); else @@ -825,6 +836,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, + root->qual_security_level, *qualscope, NULL, NULL, NULL, postponed_qual_list); } @@ -1002,6 +1014,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, distribute_qual_to_rels(root, qual, false, below_outer_join, j->jointype, + root->qual_security_level, *qualscope, ojscope, nonnullable_rels, NULL, postponed_qual_list); @@ -1059,6 +1072,67 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, } /* + * process_security_barrier_quals + * Transfer security-barrier quals into relation's baserestrictinfo list. + * + * The rewriter put any relevant security-barrier conditions into the RTE's + * securityQuals field, but it's now time to copy them into the rel's + * baserestrictinfo. + * + * In inheritance cases, we only consider quals attached to the parent rel + * here; they will be valid for all children too, so it's okay to consider + * them for purposes like equivalence class creation. Quals attached to + * individual child rels will be dealt with during path creation. + */ +static void +process_security_barrier_quals(PlannerInfo *root, + int rti, Relids qualscope, + bool below_outer_join) +{ + RangeTblEntry *rte = root->simple_rte_array[rti]; + Index security_level = 0; + ListCell *lc; + + /* + * Each element of the securityQuals list has been preprocessed into an + * implicitly-ANDed list of clauses. All the clauses in a given sublist + * should get the same security level, but successive sublists get higher + * levels. + */ + foreach(lc, rte->securityQuals) + { + List *qualset = (List *) lfirst(lc); + ListCell *lc2; + + foreach(lc2, qualset) + { + Node *qual = (Node *) lfirst(lc2); + + /* + * We cheat to the extent of passing ojscope = qualscope rather + * than its more logical value of NULL. The only effect this has + * is to force a Var-free qual to be evaluated at the rel rather + * than being pushed up to top of tree, which we don't want. + */ + distribute_qual_to_rels(root, qual, + false, + below_outer_join, + JOIN_INNER, + security_level, + qualscope, + qualscope, + NULL, + NULL, + NULL); + } + security_level++; + } + + /* Assert that qual_security_level is higher than anything we just used */ + Assert(security_level <= root->qual_security_level); +} + +/* * make_outerjoininfo * Build a SpecialJoinInfo for the current outer join * @@ -1516,6 +1590,7 @@ compute_semijoin_info(SpecialJoinInfo *sjinfo, List *clause) * 'below_outer_join': TRUE if the qual is from a JOIN/ON that is below the * nullable side of a higher-level outer join * 'jointype': type of join the qual is from (JOIN_INNER for a WHERE clause) + * 'security_level': security_level to assign to the qual * 'qualscope': set of baserels the qual's syntactic scope covers * 'ojscope': NULL if not an outer-join qual, else the minimum set of baserels * needed to form this join @@ -1545,6 +1620,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, bool is_deduced, bool below_outer_join, JoinType jointype, + Index security_level, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, @@ -1794,6 +1870,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, is_pushed_down, outerjoin_delayed, pseudoconstant, + security_level, relids, outerjoin_nonnullable, nullable_relids); @@ -2142,6 +2219,9 @@ distribute_restrictinfo_to_rels(PlannerInfo *root, /* Add clause to rel's restriction list */ rel->baserestrictinfo = lappend(rel->baserestrictinfo, restrictinfo); + /* Update security level info */ + rel->baserestrict_min_security = Min(rel->baserestrict_min_security, + restrictinfo->security_level); break; case BMS_MULTIPLE: @@ -2189,6 +2269,8 @@ distribute_restrictinfo_to_rels(PlannerInfo *root, * caller because this function is used after deconstruct_jointree, so we * don't have knowledge of where the clause items came from.) * + * "security_level" is the security level to assign to the new restrictinfo. + * * "both_const" indicates whether both items are known pseudo-constant; * in this case it is worth applying eval_const_expressions() in case we * can produce constant TRUE or constant FALSE. (Otherwise it's not, @@ -2209,6 +2291,7 @@ process_implied_equality(PlannerInfo *root, Expr *item2, Relids qualscope, Relids nullable_relids, + Index security_level, bool below_outer_join, bool both_const) { @@ -2247,6 +2330,7 @@ process_implied_equality(PlannerInfo *root, */ distribute_qual_to_rels(root, (Node *) clause, true, below_outer_join, JOIN_INNER, + security_level, qualscope, NULL, NULL, nullable_relids, NULL); } @@ -2270,7 +2354,8 @@ build_implied_join_equality(Oid opno, Expr *item1, Expr *item2, Relids qualscope, - Relids nullable_relids) + Relids nullable_relids, + Index security_level) { RestrictInfo *restrictinfo; Expr *clause; @@ -2294,6 +2379,7 @@ build_implied_join_equality(Oid opno, true, /* is_pushed_down */ false, /* outerjoin_delayed */ false, /* pseudoconstant */ + security_level, /* security_level */ qualscope, /* required_relids */ NULL, /* outer_relids */ nullable_relids); /* nullable_relids */ |