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

📄 setrefs.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
	foreach(entry, tlist)	{		AttrNumber	oattno;		xtl = lfirst(entry);		if (IsA(get_expr(xtl), Var))			oattno = ((Var *) xtl->expr)->varoattno;		else			oattno = 0;		noname = makeTargetEntry(xtl->resdom,								 (Node *) makeVar(nonameid,												  xtl->resdom->resno,												  xtl->resdom->restype,												  xtl->resdom->restypmod,												  0,												  nonameid,												  oattno));		t_list = lappend(t_list, noname);	}	return t_list;}/*--------------------------------------------------------- * * set_result_tlist_references * * Change the target list of a Result node, so that it correctly * addresses the tuples returned by its left tree subplan. * * NOTE: *	1) we ignore the right tree! (in the current implementation *	   it is always nil *	2) this routine will probably *NOT* work with nested dot *	   fields.... */static voidset_result_tlist_references(Result *resultNode){	Plan	   *subplan;	List	   *resultTargetList;	List	   *subplanTargetList;	resultTargetList = ((Plan *) resultNode)->targetlist;	/*	 * NOTE: we only consider the left tree subplan. This is usually a seq	 * scan.	 */	subplan = ((Plan *) resultNode)->lefttree;	if (subplan != NULL)		subplanTargetList = subplan->targetlist;	else		subplanTargetList = NIL;	replace_tlist_with_subplan_refs(resultTargetList,									(Index) OUTER,									subplanTargetList);}/*--------------------------------------------------------- * * replace_tlist_with_subplan_refs * * Applies replace_vars_with_subplan_refs() to each entry of a targetlist. */voidreplace_tlist_with_subplan_refs(List *tlist,								Index subvarno,								List *subplanTargetList){	List	   *t;	foreach(t, tlist)	{		TargetEntry *entry = (TargetEntry *) lfirst(t);		replace_vars_with_subplan_refs((Node *) get_expr(entry),									   subvarno, subplanTargetList);	}}/*--------------------------------------------------------- * * replace_vars_with_subplan_refs * * This routine modifies (destructively!) an expression tree so that all * Var nodes reference target nodes of a subplan.  It is used to fix up * target expressions of upper-level plan nodes. * * 'clause': the tree to be fixed * 'subvarno': varno to be assigned to all Vars * 'subplanTargetList': target list for subplan * * Afterwards, all Var nodes have varno = subvarno, varattno = resno * of corresponding subplan target. */static voidreplace_vars_with_subplan_refs(Node *clause,							   Index subvarno,							   List *subplanTargetList){	List	   *t;	if (clause == NULL)		return;	if (IsA(clause, Var))	{		/*		 * Ha! A Var node!		 *		 * It could be that this varnode has been created by make_groupplan		 * and is already set up to reference the subplan target list. We		 * recognize that case by varno = 1, varnoold = -1, varattno =		 * varoattno, and varlevelsup = 0.	(Probably ought to have an		 * explicit flag, but this should do for now.)		 */		Var		   *var = (Var *) clause;		TargetEntry *subplanVar;		if (var->varno == (Index) 1 &&			var->varnoold == ((Index) -1) &&			var->varattno == var->varoattno &&			var->varlevelsup == 0)			return;				/* OK to leave it alone */		/* Otherwise it had better be in the subplan list. */		subplanVar = match_varid(var, subplanTargetList);		if (!subplanVar)			elog(ERROR, "replace_vars_with_subplan_refs: variable not in target list");		/*		 * Change the varno & varattno fields of the var node.		 */		var->varno = subvarno;		var->varattno = subplanVar->resdom->resno;	}	else if (single_node(clause))	{		/* do nothing! */	}	else if (IsA(clause, Iter))		replace_vars_with_subplan_refs(((Iter *) clause)->iterexpr,									   subvarno, subplanTargetList);	else if (is_subplan(clause))	{		foreach(t, ((Expr *) clause)->args)			replace_vars_with_subplan_refs(lfirst(t),										   subvarno, subplanTargetList);		foreach(t, ((SubPlan *) ((Expr *) clause)->oper)->sublink->oper)			replace_vars_with_subplan_refs(lfirst(((Expr *) lfirst(t))->args),										   subvarno, subplanTargetList);	}	else if (IsA(clause, Expr))	{		/*		 * Recursively scan the arguments of an expression. NOTE: this		 * must come after is_subplan() case since subplan is a kind of		 * Expr node.		 */		foreach(t, ((Expr *) clause)->args)			replace_vars_with_subplan_refs(lfirst(t),										   subvarno, subplanTargetList);	}	else if (IsA(clause, Aggref))		replace_vars_with_subplan_refs(((Aggref *) clause)->target,									   subvarno, subplanTargetList);	else if (IsA(clause, ArrayRef))	{		ArrayRef   *aref = (ArrayRef *) clause;		foreach(t, aref->refupperindexpr)			replace_vars_with_subplan_refs(lfirst(t),										   subvarno, subplanTargetList);		foreach(t, aref->reflowerindexpr)			replace_vars_with_subplan_refs(lfirst(t),										   subvarno, subplanTargetList);		replace_vars_with_subplan_refs(aref->refexpr,									   subvarno, subplanTargetList);		replace_vars_with_subplan_refs(aref->refassgnexpr,									   subvarno, subplanTargetList);	}	else if (case_clause(clause))	{		foreach(t, ((CaseExpr *) clause)->args)		{			CaseWhen   *when = (CaseWhen *) lfirst(t);			replace_vars_with_subplan_refs(when->expr,										   subvarno, subplanTargetList);			replace_vars_with_subplan_refs(when->result,										   subvarno, subplanTargetList);		}		replace_vars_with_subplan_refs(((CaseExpr *) clause)->defresult,									   subvarno, subplanTargetList);	}	else	{		elog(ERROR, "replace_vars_with_subplan_refs: Cannot handle node type %d",			 nodeTag(clause));	}}static boolOperandIsInner(Node *opnd, int inner_relid){	/*	 * Can be the inner scan if its a varnode or a function and the	 * inner_relid is equal to the varnode's var number or in the case of	 * a function the first argument's var number (all args in a	 * functional index are from the same relation).	 */	if (IsA(opnd, Var) &&		(inner_relid == ((Var *) opnd)->varno))		return true;	if (is_funcclause(opnd))	{		List	   *firstArg = lfirst(((Expr *) opnd)->args);		if (IsA(firstArg, Var) &&			(inner_relid == ((Var *) firstArg)->varno))			return true;	}	return false;}/***************************************************************************** * *****************************************************************************//*--------------------------------------------------------- * * set_agg_tlist_references - *	  This routine has several responsibilities: *	* Update the target list of an Agg node so that it points to *	  the tuples returned by its left tree subplan. *	* If there is a qual list (from a HAVING clause), similarly update *	  vars in it to point to the subplan target list. *	* Generate the aggNode->aggs list of Aggref nodes contained in the Agg. * * The return value is TRUE if all qual clauses include Aggrefs, or FALSE * if any do not (caller may choose to raise an error condition). */boolset_agg_tlist_references(Agg *aggNode){	List	   *subplanTargetList;	List	   *tl;	List	   *ql;	bool		all_quals_ok;	subplanTargetList = aggNode->plan.lefttree->targetlist;	aggNode->aggs = NIL;	foreach(tl, aggNode->plan.targetlist)	{		TargetEntry *tle = lfirst(tl);		replace_vars_with_subplan_refs(tle->expr,									   (Index) 0,									   subplanTargetList);		aggNode->aggs = nconc(pull_agg_clause(tle->expr), aggNode->aggs);	}	all_quals_ok = true;	foreach(ql, aggNode->plan.qual)	{		Node	   *qual = lfirst(ql);		List	   *qualaggs;		replace_vars_with_subplan_refs(qual,									   (Index) 0,									   subplanTargetList);		qualaggs = pull_agg_clause(qual);		if (qualaggs == NIL)			all_quals_ok = false;		/* this qual clause has no agg										 * functions! */		else			aggNode->aggs = nconc(qualaggs, aggNode->aggs);	}	return all_quals_ok;}/* * Make a list of all Aggref nodes contained in the given expression. */static List *pull_agg_clause(Node *clause){	List	   *agg_list = NIL;	List	   *t;	if (clause == NULL)		return NIL;	else if (single_node(clause))		return NIL;	else if (IsA(clause, Iter))		return pull_agg_clause(((Iter *) clause)->iterexpr);	else if (is_subplan(clause))	{		SubLink    *sublink = ((SubPlan *) ((Expr *) clause)->oper)->sublink;		/*		 * Only the lefthand side of the sublink should be checked for		 * aggregates to be attached to the aggs list		 */		foreach(t, sublink->lefthand)			agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);		/* The first argument of ...->oper has also to be checked */		foreach(t, sublink->oper)			agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);	}	else if (IsA(clause, Expr))	{		/*		 * Recursively scan the arguments of an expression. NOTE: this		 * must come after is_subplan() case since subplan is a kind of		 * Expr node.		 */		foreach(t, ((Expr *) clause)->args)			agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);	}	else if (IsA(clause, Aggref))	{		return lcons(clause,					 pull_agg_clause(((Aggref *) clause)->target));	}	else if (IsA(clause, ArrayRef))	{		ArrayRef   *aref = (ArrayRef *) clause;		foreach(t, aref->refupperindexpr)			agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);		foreach(t, aref->reflowerindexpr)			agg_list = nconc(pull_agg_clause(lfirst(t)), agg_list);		agg_list = nconc(pull_agg_clause(aref->refexpr), agg_list);		agg_list = nconc(pull_agg_clause(aref->refassgnexpr), agg_list);	}	else if (case_clause(clause))	{		foreach(t, ((CaseExpr *) clause)->args)		{			CaseWhen   *when = (CaseWhen *) lfirst(t);			agg_list = nconc(agg_list, pull_agg_clause(when->expr));			agg_list = nconc(agg_list, pull_agg_clause(when->result));		}		agg_list = nconc(pull_agg_clause(((CaseExpr *) clause)->defresult),						 agg_list);	}	else	{		elog(ERROR, "pull_agg_clause: Cannot handle node type %d",			 nodeTag(clause));	}	return agg_list;}/* * check_having_for_ungrouped_vars takes the havingQual and the list of * GROUP BY clauses and checks for subplans in the havingQual that are being * passed ungrouped variables as parameters.  In other contexts, ungrouped * vars in the havingQual will be detected by the parser (see parse_agg.c, * exprIsAggOrGroupCol()).	But that routine currently does not check subplans, * because the necessary info is not computed until the planner runs. * This ought to be cleaned up someday. * * NOTE: the havingClause has been cnf-ified, so AND subclauses have been * turned into a plain List.  Thus, this routine has to cope with List nodes * where the routine above does not... */voidcheck_having_for_ungrouped_vars(Node *clause, List *groupClause,								List *targetList){	List	   *t;	if (clause == NULL)		return;	if (IsA(clause, Var))	{		/*		 * Ignore vars elsewhere in the having clause, since the parser		 * already checked 'em.		 */	}	else if (single_node(clause))	{		/* ignore */	}	else if (IsA(clause, Iter))	{		check_having_for_ungrouped_vars(((Iter *) clause)->iterexpr,										groupClause, targetList);	}	else if (is_subplan(clause))	{		/*		 * The args list of the subplan node represents attributes from		 * outside passed into the sublink.		 */		foreach(t, ((Expr *) clause)->args)		{			bool		contained_in_group_clause = false;			List	   *gl;			foreach(gl, groupClause)			{				if (var_equal(lfirst(t),							  get_groupclause_expr((GroupClause *)												lfirst(gl), targetList)))				{					contained_in_group_clause = true;					break;				}			}			if (!contained_in_group_clause)				elog(ERROR, "Sub-SELECT in HAVING clause must use only GROUPed attributes from outer SELECT");		}	}	else if (IsA(clause, Expr))	{		/*		 * Recursively scan the arguments of an expression. NOTE: this		 * must come after is_subplan() case since subplan is a kind of		 * Expr node.		 */		foreach(t, ((Expr *) clause)->args)			check_having_for_ungrouped_vars(lfirst(t), groupClause,											targetList);	}	else if (IsA(clause, List))	{		/*		 * Recursively scan AND subclauses (see NOTE above).		 */		foreach(t, ((List *) clause))			check_having_for_ungrouped_vars(lfirst(t), groupClause,											targetList);	}	else if (IsA(clause, Aggref))	{		check_having_for_ungrouped_vars(((Aggref *) clause)->target,										groupClause, targetList);	}	else if (IsA(clause, ArrayRef))	{		ArrayRef   *aref = (ArrayRef *) clause;		/*		 * This is an arrayref. Recursively call this routine for its		 * expression and its index expression...		 */		foreach(t, aref->refupperindexpr)			check_having_for_ungrouped_vars(lfirst(t), groupClause,											targetList);		foreach(t, aref->reflowerindexpr)			check_having_for_ungrouped_vars(lfirst(t), groupClause,											targetList);		check_having_for_ungrouped_vars(aref->refexpr, groupClause,										targetList);		check_having_for_ungrouped_vars(aref->refassgnexpr, groupClause,										targetList);	}	else if (case_clause(clause))	{		foreach(t, ((CaseExpr *) clause)->args)		{			CaseWhen   *when = (CaseWhen *) lfirst(t);			check_having_for_ungrouped_vars(when->expr, groupClause,											targetList);			check_having_for_ungrouped_vars(when->result, groupClause,											targetList);		}		check_having_for_ungrouped_vars(((CaseExpr *) clause)->defresult,										groupClause, targetList);	}	else	{		elog(ERROR, "check_having_for_ungrouped_vars: Cannot handle node type %d",			 nodeTag(clause));	}}

⌨️ 快捷键说明

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