📄 prepunion.c
字号:
inhRTIs = makeListi1(rti); /* include original RTE in result */ foreach(l, inhOIDs) { Oid childOID = lfirsto(l); RangeTblEntry *childrte; Index childRTindex; /* parent will be in the list too; skip it if not dup requested */ if (childOID == parentOID && !dup_parent) continue; /* * Build an RTE for the child, and attach to query's rangetable * list. We copy most fields of the parent's RTE, but replace * relation real name and OID. Note that inh will be false at * this point. */ childrte = copyObject(rte); childrte->relid = childOID; parse->rtable = lappend(parse->rtable, childrte); childRTindex = length(parse->rtable); inhRTIs = lappendi(inhRTIs, childRTindex); } return inhRTIs;}/* * adjust_inherited_attrs * Copy the specified query or expression and translate Vars referring * to old_rt_index to refer to new_rt_index. * * We also adjust varattno to match the new table by column name, rather * than column number. This hack makes it possible for child tables to have * different column positions for the "same" attribute as a parent, which * helps ALTER TABLE ADD COLUMN. Unfortunately this isn't nearly enough to * make it work transparently; there are other places where things fall down * if children and parents don't have the same column numbers for inherited * attributes. It'd be better to rip this code out and fix ALTER TABLE... */Node *adjust_inherited_attrs(Node *node, Index old_rt_index, Oid old_relid, Index new_rt_index, Oid new_relid){ adjust_inherited_attrs_context context; /* Handle simple case simply... */ if (old_rt_index == new_rt_index) { Assert(old_relid == new_relid); return copyObject(node); } context.old_rt_index = old_rt_index; context.new_rt_index = new_rt_index; context.old_relid = old_relid; context.new_relid = new_relid; /* * Must be prepared to start with a Query or a bare expression tree. */ if (node && IsA(node, Query)) { Query *newnode; newnode = query_tree_mutator((Query *) node, adjust_inherited_attrs_mutator, (void *) &context, QTW_IGNORE_RT_SUBQUERIES); if (newnode->resultRelation == old_rt_index) { newnode->resultRelation = new_rt_index; /* Fix tlist resnos too, if it's inherited UPDATE */ if (newnode->commandType == CMD_UPDATE) newnode->targetList = adjust_inherited_tlist(newnode->targetList, old_relid, new_relid); } return (Node *) newnode; } else return adjust_inherited_attrs_mutator(node, &context);}static Node *adjust_inherited_attrs_mutator(Node *node, adjust_inherited_attrs_context *context){ if (node == NULL) return NULL; if (IsA(node, Var)) { Var *var = (Var *) copyObject(node); if (var->varlevelsup == 0 && var->varno == context->old_rt_index) { var->varno = context->new_rt_index; var->varnoold = context->new_rt_index; if (var->varattno > 0) { char *attname; attname = get_relid_attribute_name(context->old_relid, var->varattno); var->varattno = get_attnum(context->new_relid, attname); if (var->varattno == InvalidAttrNumber) elog(ERROR, "attribute \"%s\" of relation \"%s\" does not exist", attname, get_rel_name(context->new_relid)); var->varoattno = var->varattno; pfree(attname); } } return (Node *) var; } if (IsA(node, RangeTblRef)) { RangeTblRef *rtr = (RangeTblRef *) copyObject(node); if (rtr->rtindex == context->old_rt_index) rtr->rtindex = context->new_rt_index; return (Node *) rtr; } if (IsA(node, JoinExpr)) { /* Copy the JoinExpr node with correct mutation of subnodes */ JoinExpr *j; j = (JoinExpr *) expression_tree_mutator(node, adjust_inherited_attrs_mutator, (void *) context); /* now fix JoinExpr's rtindex */ if (j->rtindex == context->old_rt_index) j->rtindex = context->new_rt_index; return (Node *) j; } if (IsA(node, InClauseInfo)) { /* Copy the InClauseInfo node with correct mutation of subnodes */ InClauseInfo *ininfo; ininfo = (InClauseInfo *) expression_tree_mutator(node, adjust_inherited_attrs_mutator, (void *) context); /* now fix InClauseInfo's relid sets */ ininfo->lefthand = adjust_relid_set(ininfo->lefthand, context->old_rt_index, context->new_rt_index); ininfo->righthand = adjust_relid_set(ininfo->righthand, context->old_rt_index, context->new_rt_index); return (Node *) ininfo; } /* * We have to process RestrictInfo nodes specially. */ if (IsA(node, RestrictInfo)) { RestrictInfo *oldinfo = (RestrictInfo *) node; RestrictInfo *newinfo = makeNode(RestrictInfo); /* Copy all flat-copiable fields */ memcpy(newinfo, oldinfo, sizeof(RestrictInfo)); /* Recursively fix the clause itself */ newinfo->clause = (Expr *) adjust_inherited_attrs_mutator((Node *) oldinfo->clause, context); /* * We do NOT want to copy the original subclauseindices list, * since the new rel will have different indices. The list will * be rebuilt when needed during later planning. */ newinfo->subclauseindices = NIL; /* * Adjust left/right relid sets too. */ newinfo->left_relids = adjust_relid_set(oldinfo->left_relids, context->old_rt_index, context->new_rt_index); newinfo->right_relids = adjust_relid_set(oldinfo->right_relids, context->old_rt_index, context->new_rt_index); newinfo->eval_cost.startup = -1; /* reset these too */ newinfo->this_selec = -1; newinfo->left_pathkey = NIL; /* and these */ newinfo->right_pathkey = NIL; newinfo->left_mergescansel = -1; newinfo->right_mergescansel = -1; newinfo->left_bucketsize = -1; newinfo->right_bucketsize = -1; return (Node *) newinfo; } /* * NOTE: we do not need to recurse into sublinks, because they should * already have been converted to subplans before we see them. */ Assert(!IsA(node, SubLink)); Assert(!IsA(node, Query)); /* * BUT: although we don't need to recurse into subplans, we do need to * make sure that they are copied, not just referenced as * expression_tree_mutator will do by default. Otherwise we'll have * the same subplan node referenced from each arm of the inheritance * APPEND plan, which will cause trouble in the executor. This is a * kluge that should go away when we redesign querytrees. */ if (is_subplan(node)) { SubPlan *subplan; /* Copy the node and process subplan args */ node = expression_tree_mutator(node, adjust_inherited_attrs_mutator, (void *) context); /* Make sure we have separate copies of subplan and its rtable */ subplan = (SubPlan *) node; subplan->plan = copyObject(subplan->plan); subplan->rtable = copyObject(subplan->rtable); return node; } return expression_tree_mutator(node, adjust_inherited_attrs_mutator, (void *) context);}/* * Substitute newrelid for oldrelid in a Relid set */static Relidsadjust_relid_set(Relids relids, Index oldrelid, Index newrelid){ if (bms_is_member(oldrelid, relids)) { /* Ensure we have a modifiable copy */ relids = bms_copy(relids); /* Remove old, add new */ relids = bms_del_member(relids, oldrelid); relids = bms_add_member(relids, newrelid); } return relids;}/* * Adjust the targetlist entries of an inherited UPDATE operation * * The expressions have already been fixed, but we have to make sure that * the target resnos match the child table (they may not, in the case of * a column that was added after-the-fact by ALTER TABLE). In some cases * this can force us to re-order the tlist to preserve resno ordering. * (We do all this work in special cases so that preptlist.c is fast for * the typical case.) * * The given tlist has already been through expression_tree_mutator; * therefore the TargetEntry nodes are fresh copies that it's okay to * scribble on. But the Resdom nodes have not been copied; make new ones * if we need to change them! * * Note that this is not needed for INSERT because INSERT isn't inheritable. */static List *adjust_inherited_tlist(List *tlist, Oid old_relid, Oid new_relid){ bool changed_it = false; List *tl; List *new_tlist; bool more; int attrno; /* Scan tlist and update resnos to match attnums of new_relid */ foreach(tl, tlist) { TargetEntry *tle = (TargetEntry *) lfirst(tl); Resdom *resdom = tle->resdom; char *attname; if (resdom->resjunk) continue; /* ignore junk items */ attname = get_relid_attribute_name(old_relid, resdom->resno); attrno = get_attnum(new_relid, attname); if (attrno == InvalidAttrNumber) elog(ERROR, "attribute \"%s\" of relation \"%s\" does not exist", attname, get_rel_name(new_relid)); if (resdom->resno != attrno) { resdom = (Resdom *) copyObject((Node *) resdom); resdom->resno = attrno; resdom->resname = attname; tle->resdom = resdom; changed_it = true; } else pfree(attname); } /* * If we changed anything, re-sort the tlist by resno, and make sure * resjunk entries have resnos above the last real resno. The sort * algorithm is a bit stupid, but for such a seldom-taken path, small * is probably better than fast. */ if (!changed_it) return tlist; new_tlist = NIL; more = true; for (attrno = 1; more; attrno++) { more = false; foreach(tl, tlist) { TargetEntry *tle = (TargetEntry *) lfirst(tl); Resdom *resdom = tle->resdom; if (resdom->resjunk) continue; /* ignore junk items */ if (resdom->resno == attrno) new_tlist = lappend(new_tlist, tle); else if (resdom->resno > attrno) more = true; } } foreach(tl, tlist) { TargetEntry *tle = (TargetEntry *) lfirst(tl); Resdom *resdom = tle->resdom; if (!resdom->resjunk) continue; /* here, ignore non-junk items */ if (resdom->resno != attrno) { resdom = (Resdom *) copyObject((Node *) resdom); resdom->resno = attrno; tle->resdom = resdom; } new_tlist = lappend(new_tlist, tle); attrno++; } return new_tlist;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -