⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prepunion.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -