/* *IfparentrelationisselectedFORUPDATE/SHARE,weneedtomarkits *PlanRowMarkasisParent=true,andgenerateanewPlanRowMarkforeach *child.
*/
oldrc = get_plan_rowmark(root->rowMarks, rti); if (oldrc)
{
old_isParent = oldrc->isParent;
oldrc->isParent = true; /* Save initial value of allMarkTypes before children add to it */
old_allMarkTypes = oldrc->allMarkTypes;
}
/* Scan the inheritance set and expand it */ if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
RTEPermissionInfo *perminfo;
/* Expand simple_rel_array and friends to hold child objects. */
expand_planner_arrays(root, list_length(inhOIDs));
/* *ExpandinheritancechildrenintheordertheOIDswerereturnedby *find_all_inheritors.
*/
foreach(l, inhOIDs)
{
Oid childOID = lfirst_oid(l);
Relation newrelation;
RangeTblEntry *childrte;
Index childRTindex;
/* Open rel if needed; we already have required locks */ if (childOID != parentOID)
newrelation = table_open(childOID, NoLock); else
newrelation = oldrelation;
/* Close child relations, but keep locks */ if (childOID != parentOID)
table_close(newrelation, NoLock);
}
}
/* *Somechildrenmightrequiredifferentmarktypes,whichwould'vebeen *reportedintooldrc.Ifso,addrelevantentriestothetop-level *targetlistandupdateparentrel'sreltarget.Thisshouldmatchwhat *preprocess_targetlist()wouldhaveaddedifthemarktypeshadbeen *requestedoriginally. * *(Somedayitmightbeusefultofoldtheseresjunkcolumnsintothe *row-identity-columnmanagementusedforUPDATE/DELETE.Todayisnot *thatday,however.)
*/ if (oldrc)
{ int new_allMarkTypes = oldrc->allMarkTypes;
Var *var;
TargetEntry *tle; char resname[32];
List *newvars = NIL;
/* Add TID junk Var if needed, unless we had it already */ if (new_allMarkTypes & ~(1 << ROW_MARK_COPY) &&
!(old_allMarkTypes & ~(1 << ROW_MARK_COPY)))
{ /* Need to fetch TID */
var = makeVar(oldrc->rti,
SelfItemPointerAttributeNumber,
TIDOID,
-1,
InvalidOid, 0);
snprintf(resname, sizeof(resname), "ctid%u", oldrc->rowmarkId);
tle = makeTargetEntry((Expr *) var,
list_length(root->processed_tlist) + 1,
pstrdup(resname), true);
root->processed_tlist = lappend(root->processed_tlist, tle);
newvars = lappend(newvars, var);
}
/* Add whole-row junk Var if needed, unless we had it already */ if ((new_allMarkTypes & (1 << ROW_MARK_COPY)) &&
!(old_allMarkTypes & (1 << ROW_MARK_COPY)))
{
var = makeWholeRowVar(planner_rt_fetch(oldrc->rti, root),
oldrc->rti, 0, false);
snprintf(resname, sizeof(resname), "wholerow%u", oldrc->rowmarkId);
tle = makeTargetEntry((Expr *) var,
list_length(root->processed_tlist) + 1,
pstrdup(resname), true);
root->processed_tlist = lappend(root->processed_tlist, tle);
newvars = lappend(newvars, var);
}
/* Add tableoid junk Var, unless we had it already */ if (!old_isParent)
{
var = makeVar(oldrc->rti,
TableOidAttributeNumber,
OIDOID,
-1,
InvalidOid, 0);
snprintf(resname, sizeof(resname), "tableoid%u", oldrc->rowmarkId);
tle = makeTargetEntry((Expr *) var,
list_length(root->processed_tlist) + 1,
pstrdup(resname), true);
root->processed_tlist = lappend(root->processed_tlist, tle);
newvars = lappend(newvars, var);
}
/* Expand simple_rel_array and friends to hold child objects. */
num_live_parts = bms_num_members(relinfo->live_parts); if (num_live_parts > 0)
expand_planner_arrays(root, num_live_parts);
/* *Temporarypartitionsbelongingtoothersessionsshouldhavebeen *disallowedatdefinition,butforparanoia'ssake,let'sdouble *check.
*/ if (RELATION_IS_OTHER_TEMP(childrel))
elog(ERROR, "temporary relation from another session found as partition");
/* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
expand_single_inheritance_child(root, parentrte, parentRTindex,
parentrel, top_parentrc, childrel,
&childrte, &childRTindex);
/* If this child is itself partitioned, recurse */ if (childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
{
AppendRelInfo *appinfo = root->append_rel_array[childRTindex];
Bitmapset *child_updatedCols;
if (att->attisdropped)
{ /* Always insert an empty string for a dropped column */
attname = "";
} elseif (appinfo->parent_colnos[cattno] > 0 &&
appinfo->parent_colnos[cattno] <= list_length(parent_colnames))
{ /* Duplicate the query-assigned name for the parent column */
attname = strVal(list_nth(parent_colnames,
appinfo->parent_colnos[cattno] - 1));
} else
{ /* New column, just use its real name */
attname = NameStr(att->attname);
}
child_colnames = lappend(child_colnames, makeString(pstrdup(attname)));
}
/* *Ifwearecreatingachildofthequerytargetrelation(onlypossible *inUPDATE/DELETE/MERGE),addittoall_result_relids,aswellas *leaf_result_relidsifappropriate,andmakesurethatwegenerate *requiredrow-identitydata.
*/ if (bms_is_member(parentRTindex, root->all_result_relids))
{ /* OK, record the child as a result rel too. */
root->all_result_relids = bms_add_member(root->all_result_relids,
childRTindex);
/* Non-leaf partitions don't need any row identity info. */ if (childrte->relkind != RELKIND_PARTITIONED_TABLE)
{
Var *rrvar;
/* System attributes have the same numbers in all tables */ for (attno = FirstLowInvalidHeapAttributeNumber + 1; attno < 0; attno++)
{ if (bms_is_member(attno - FirstLowInvalidHeapAttributeNumber,
parent_privs))
child_privs = bms_add_member(child_privs,
attno - FirstLowInvalidHeapAttributeNumber);
}
/* Check if parent has whole-row reference */
whole_row = bms_is_member(InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber,
parent_privs);
/* And now translate the regular user attributes, using the vars list */
attno = InvalidAttrNumber;
foreach(lc, translated_vars)
{
Var *var = lfirst_node(Var, lc);
/* Fast path for easy case. */ if (parent_cols == NULL) return NULL;
/* Recurse if immediate parent is not the top parent. */ if (rel->parent != parent_rel)
{ if (rel->parent)
parent_cols = translate_col_privs_multilevel(root, rel->parent,
parent_rel,
parent_cols); else
elog(ERROR, "rel with relid %u is not a child rel", rel->relid);
}
/* Now translate for this child. */
Assert(root->append_rel_array != NULL);
appinfo = root->append_rel_array[rel->relid];
Assert(appinfo != NULL);
/* Child may itself be an inherited rel, either table or subquery. */ if (childrte->inh)
expand_inherited_rtentry(root, childrel, childrte, childRTindex);
}
}
Assert(IsA(rinfo, RestrictInfo));
childqual = adjust_appendrel_attrs(root,
(Node *) rinfo->clause, 1, &appinfo);
childqual = eval_const_expressions(root, childqual); /* check for flat-out constant */ if (childqual && IsA(childqual, Const))
{ if (((Const *) childqual)->constisnull ||
!DatumGetBool(((Const *) childqual)->constvalue))
{ /* Restriction reduces to constant FALSE or NULL */ returnfalse;
} /* Restriction reduces to constant TRUE, so drop it */ continue;
} /* might have gotten an AND clause, if so flatten it */
foreach(lc2, make_ands_implicit((Expr *) childqual))
{
Node *onecq = (Node *) lfirst(lc2); bool pseudoconstant;
RestrictInfo *childrinfo;
/* check for pseudoconstant (no Vars or volatile functions) */
pseudoconstant =
!contain_vars_of_level(onecq, 0) &&
!contain_volatile_functions(onecq); if (pseudoconstant)
{ /* tell createplan.c to check for gating quals */
root->hasPseudoConstantQuals = true;
} /* reconstitute RestrictInfo with appropriate properties */
childrinfo = make_restrictinfo(root,
(Expr *) onecq,
rinfo->is_pushed_down,
rinfo->has_clone,
rinfo->is_clone,
pseudoconstant,
rinfo->security_level,
NULL, NULL, NULL);
/* Restriction is proven always false */ if (restriction_is_always_false(root, childrinfo)) returnfalse; /* Restriction is proven always true, so drop it */ if (restriction_is_always_true(root, childrinfo)) continue;
childquals = lappend(childquals, childrinfo); /* track minimum security level among child quals */
cq_min_security = Min(cq_min_security, rinfo->security_level);
}
}
/* *Inadditiontothequalsinheritedfromtheparent,wemighthave *securityQualsassociatedwiththisparticularchildnode.(Currently *thiscanonlyhappeninappendrelsoriginatingfromUNIONALL; *inheritancechildtablesdon'thavetheirownsecurityQuals,see *expand_single_inheritance_child().)PullanysuchsecurityQualsup *intothebaserestrictinfoforthechild.Thisissimilarto *process_security_barrier_quals()fortheparentrel,exceptthatwe *can'tmakeanygeneraldeductionsfromsuchquals,sincetheydon't *holdforthewholeappendrel.
*/ if (childRTE->securityQuals)
{
Index security_level = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.