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

📄 setrefs.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * setrefs.c *	  Routines to change varno/attno entries to contain references * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.50.2.1 1999/08/02 06:27:03 scrappy Exp $ * *------------------------------------------------------------------------- */#include <sys/types.h>#include "postgres.h"#include "nodes/makefuncs.h"#include "nodes/nodeFuncs.h"#include "optimizer/clauses.h"#include "optimizer/planmain.h"#include "optimizer/tlist.h"#include "optimizer/var.h"static void set_join_tlist_references(Join *join);static void set_nonamescan_tlist_references(SeqScan *nonamescan);static void set_noname_tlist_references(Noname *noname);static Node *replace_clause_joinvar_refs(Node *clause,							List *outer_tlist,							List *inner_tlist);static Var *replace_joinvar_refs(Var *var,					 List *outer_tlist,					 List *inner_tlist);static List *tlist_noname_references(Oid nonameid, List *tlist);static bool OperandIsInner(Node *opnd, int inner_relid);static List *pull_agg_clause(Node *clause);static void set_result_tlist_references(Result *resultNode);static void replace_vars_with_subplan_refs(Node *clause,							   Index subvarno,							   List *subplanTargetList);/***************************************************************************** * *		SUBPLAN REFERENCES * *****************************************************************************//* * set_tlist_references *	  Modifies the target list of nodes in a plan to reference target lists *	  at lower levels. * * 'plan' is the plan whose target list and children's target lists will *		be modified * * Returns nothing of interest, but modifies internal fields of nodes. * */voidset_tlist_references(Plan *plan){	if (plan == NULL)		return;	if (IsA_Join(plan))		set_join_tlist_references((Join *) plan);	else if (IsA(plan, SeqScan) &&plan->lefttree &&			 IsA_Noname(plan->lefttree))		set_nonamescan_tlist_references((SeqScan *) plan);	else if (IsA(plan, Sort))		set_noname_tlist_references((Noname *) plan);	else if (IsA(plan, Result))		set_result_tlist_references((Result *) plan);	else if (IsA(plan, Hash))		set_tlist_references(plan->lefttree);}/* * set_join_tlist_references *	  Modifies the target list of a join node by setting the varnos and *	  varattnos to reference the target list of the outer and inner join *	  relations. * *	  Creates a target list for a join node to contain references by setting *	  varno values to OUTER or INNER and setting attno values to the *	  result domain number of either the corresponding outer or inner join *	  tuple. * * 'join' is a join plan node * * Returns nothing of interest, but modifies internal fields of nodes. * */static voidset_join_tlist_references(Join *join){	Plan	   *outer = ((Plan *) join)->lefttree;	Plan	   *inner = ((Plan *) join)->righttree;	List	   *outer_tlist = ((outer == NULL) ? NIL : outer->targetlist);	List	   *inner_tlist = ((inner == NULL) ? NIL : inner->targetlist);	List	   *new_join_targetlist = NIL;	List	   *qptlist = ((Plan *) join)->targetlist;	List	   *entry;	foreach(entry, qptlist)	{		TargetEntry *xtl = (TargetEntry *) lfirst(entry);		Node	   *joinvar = replace_clause_joinvar_refs(xtl->expr,														  outer_tlist,														  inner_tlist);		new_join_targetlist = lappend(new_join_targetlist,								  makeTargetEntry(xtl->resdom, joinvar));	}	((Plan *) join)->targetlist = new_join_targetlist;	if (outer != NULL)		set_tlist_references(outer);	if (inner != NULL)		set_tlist_references(inner);}/* * set_nonamescan_tlist_references *	  Modifies the target list of a node that scans a noname relation (i.e., a *	  sort or hash node) so that the varnos refer to the child noname. * * 'nonamescan' is a seqscan node * * Returns nothing of interest, but modifies internal fields of nodes. * */static voidset_nonamescan_tlist_references(SeqScan *nonamescan){	Noname	   *noname = (Noname *) ((Plan *) nonamescan)->lefttree;	((Plan *) nonamescan)->targetlist = tlist_noname_references(noname->nonameid,									  ((Plan *) nonamescan)->targetlist);	set_noname_tlist_references(noname);}/* * set_noname_tlist_references *	  The noname's vars are made consistent with (actually, identical to) the *	  modified version of the target list of the node from which noname node *	  receives its tuples. * * 'noname' is a noname (e.g., sort, hash) plan node * * Returns nothing of interest, but modifies internal fields of nodes. * */static voidset_noname_tlist_references(Noname *noname){	Plan	   *source = ((Plan *) noname)->lefttree;	if (source != NULL)	{		set_tlist_references(source);		((Plan *) noname)->targetlist = copy_vars(((Plan *) noname)->targetlist,												  (source)->targetlist);	}	else		elog(ERROR, "calling set_noname_tlist_references with empty lefttree");}/* * join_references *	   Creates a new set of join clauses by changing the varno/varattno *	   values of variables in the clauses to reference target list values *	   from the outer and inner join relation target lists. *	   This is just an external interface for replace_clause_joinvar_refs. * * 'clauses' is the list of join clauses * 'outer_tlist' is the target list of the outer join relation * 'inner_tlist' is the target list of the inner join relation * * Returns the new join clauses.  The original clause structure is * not modified. * */List *join_references(List *clauses,				List *outer_tlist,				List *inner_tlist){	return (List *) replace_clause_joinvar_refs((Node *) clauses,												outer_tlist,												inner_tlist);}/* * index_outerjoin_references *	  Given a list of join clauses, replace the operand corresponding to the *	  outer relation in the join with references to the corresponding target *	  list element in 'outer_tlist' (the outer is rather obscurely *	  identified as the side that doesn't contain a var whose varno equals *	  'inner_relid'). * *	  As a side effect, the operator is replaced by the regproc id. * * 'inner_indxqual' is the list of join clauses (so-called because they * are used as qualifications for the inner (inbex) scan of a nestloop) * * Returns the new list of clauses. * */List *index_outerjoin_references(List *inner_indxqual,						   List *outer_tlist,						   Index inner_relid){	List	   *t_list = NIL;	Expr	   *temp = NULL;	List	   *t_clause = NIL;	Expr	   *clause = NULL;	foreach(t_clause, inner_indxqual)	{		clause = lfirst(t_clause);		/*		 * if inner scan on the right.		 */		if (OperandIsInner((Node *) get_rightop(clause), inner_relid))		{			Var		   *joinvar = (Var *)			replace_clause_joinvar_refs((Node *) get_leftop(clause),										outer_tlist,										NIL);			temp = make_opclause(replace_opid((Oper *) ((Expr *) clause)->oper),								 joinvar,								 get_rightop(clause));			t_list = lappend(t_list, temp);		}		else		{			/* inner scan on left */			Var		   *joinvar = (Var *)			replace_clause_joinvar_refs((Node *) get_rightop(clause),										outer_tlist,										NIL);			temp = make_opclause(replace_opid((Oper *) ((Expr *) clause)->oper),								 get_leftop(clause),								 joinvar);			t_list = lappend(t_list, temp);		}	}	return t_list;}/* * replace_clause_joinvar_refs * replace_joinvar_refs * *	  Replaces all variables within a join clause with a new var node *	  whose varno/varattno fields contain a reference to a target list *	  element from either the outer or inner join relation. * * 'clause' is the join clause * 'outer_tlist' is the target list of the outer join relation * 'inner_tlist' is the target list of the inner join relation * * Returns the new join clause. * NB: it is critical that the original clause structure not be modified! * The changes must be applied to a copy. * * XXX the current implementation does not copy unchanged primitive * nodes; they remain shared with the original.  Is this safe? */static Node *replace_clause_joinvar_refs(Node *clause,							List *outer_tlist,							List *inner_tlist){	if (clause == NULL)		return NULL;	if (IsA(clause, Var))	{		Var		   *temp = replace_joinvar_refs((Var *) clause,												outer_tlist, inner_tlist);		if (temp != NULL)			return (Node *) temp;		else			return clause;	}	else if (single_node(clause))		return clause;	else if (and_clause(clause))	{		return (Node *) make_andclause((List *)			replace_clause_joinvar_refs((Node *) ((Expr *) clause)->args,										outer_tlist,										inner_tlist));	}	else if (or_clause(clause))	{		return (Node *) make_orclause((List *)			replace_clause_joinvar_refs((Node *) ((Expr *) clause)->args,										outer_tlist,										inner_tlist));	}	else if (IsA(clause, ArrayRef))	{		ArrayRef   *oldnode = (ArrayRef *) clause;		ArrayRef   *newnode = makeNode(ArrayRef);		newnode->refattrlength = oldnode->refattrlength;		newnode->refelemlength = oldnode->refelemlength;		newnode->refelemtype = oldnode->refelemtype;		newnode->refelembyval = oldnode->refelembyval;		newnode->refupperindexpr = (List *)			replace_clause_joinvar_refs((Node *) oldnode->refupperindexpr,										outer_tlist,										inner_tlist);		newnode->reflowerindexpr = (List *)			replace_clause_joinvar_refs((Node *) oldnode->reflowerindexpr,										outer_tlist,										inner_tlist);		newnode->refexpr =			replace_clause_joinvar_refs(oldnode->refexpr,										outer_tlist,										inner_tlist);		newnode->refassgnexpr =			replace_clause_joinvar_refs(oldnode->refassgnexpr,										outer_tlist,										inner_tlist);		return (Node *) newnode;	}	else if (is_funcclause(clause))	{		return (Node *) make_funcclause(										(Func *) ((Expr *) clause)->oper,									(List *) replace_clause_joinvar_refs(										(Node *) ((Expr *) clause)->args,															 outer_tlist,														   inner_tlist));	}	else if (not_clause(clause))	{		return (Node *) make_notclause((Expr *)									   replace_clause_joinvar_refs(							  (Node *) get_notclausearg((Expr *) clause),															 outer_tlist,														   inner_tlist));	}	else if (is_opclause(clause))	{		return (Node *) make_opclause(						  replace_opid((Oper *) ((Expr *) clause)->oper),									  (Var *) replace_clause_joinvar_refs(									(Node *) get_leftop((Expr *) clause),															 outer_tlist,															inner_tlist),									  (Var *) replace_clause_joinvar_refs(								   (Node *) get_rightop((Expr *) clause),															 outer_tlist,														   inner_tlist));	}	else if (IsA(clause, List))	{		List	   *t_list = NIL;		List	   *subclause;		foreach(subclause, (List *) clause)		{			t_list = lappend(t_list,						   replace_clause_joinvar_refs(lfirst(subclause),													   outer_tlist,													   inner_tlist));		}		return (Node *) t_list;	}	else if (is_subplan(clause))	{		/* This is a tad wasteful of space, but it works... */		Expr	   *newclause = (Expr *) copyObject(clause);		newclause->args = (List *)			replace_clause_joinvar_refs((Node *) newclause->args,										outer_tlist,										inner_tlist);		((SubPlan *) newclause->oper)->sublink->oper = (List *)			replace_clause_joinvar_refs(				   (Node *) ((SubPlan *) newclause->oper)->sublink->oper,										outer_tlist,										inner_tlist);		return (Node *) newclause;	}	else if (IsA(clause, CaseExpr))	{		CaseExpr   *oldnode = (CaseExpr *) clause;		CaseExpr   *newnode = makeNode(CaseExpr);		newnode->casetype = oldnode->casetype;		newnode->arg = oldnode->arg;	/* XXX should always be null										 * anyway ... */		newnode->args = (List *)			replace_clause_joinvar_refs((Node *) oldnode->args,										outer_tlist,										inner_tlist);		newnode->defresult =			replace_clause_joinvar_refs(oldnode->defresult,										outer_tlist,										inner_tlist);		return (Node *) newnode;	}	else if (IsA(clause, CaseWhen))	{		CaseWhen   *oldnode = (CaseWhen *) clause;		CaseWhen   *newnode = makeNode(CaseWhen);		newnode->expr =			replace_clause_joinvar_refs(oldnode->expr,										outer_tlist,										inner_tlist);		newnode->result =			replace_clause_joinvar_refs(oldnode->result,										outer_tlist,										inner_tlist);		return (Node *) newnode;	}	else	{		elog(ERROR, "replace_clause_joinvar_refs: unsupported clause %d",			 nodeTag(clause));		return NULL;	}}static Var *replace_joinvar_refs(Var *var, List *outer_tlist, List *inner_tlist){	Resdom	   *outer_resdom;	outer_resdom = tlist_member(var, outer_tlist);	if (outer_resdom != NULL && IsA(outer_resdom, Resdom))	{		return (makeVar(OUTER,						outer_resdom->resno,						var->vartype,						var->vartypmod,						0,						var->varnoold,						var->varoattno));	}	else	{		Resdom	   *inner_resdom;		inner_resdom = tlist_member(var, inner_tlist);		if (inner_resdom != NULL && IsA(inner_resdom, Resdom))		{			return (makeVar(INNER,							inner_resdom->resno,							var->vartype,							var->vartypmod,							0,							var->varnoold,							var->varoattno));		}	}	return (Var *) NULL;}/* * tlist_noname_references *	  Creates a new target list for a node that scans a noname relation, *	  setting the varnos to the id of the noname relation and setting varids *	  if necessary (varids are only needed if this is a targetlist internal *	  to the tree, in which case the targetlist entry always contains a var *	  node, so we can just copy it from the noname). * * 'nonameid' is the id of the noname relation * 'tlist' is the target list to be modified * * Returns new target list * */static List *tlist_noname_references(Oid nonameid,						List *tlist){	List	   *t_list = NIL;	TargetEntry *noname = (TargetEntry *) NULL;	TargetEntry *xtl = NULL;	List	   *entry;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -