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

📄 subselect.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
	{		SubPlan	   *subplan = (SubPlan *) ((Expr *) node)->oper;		List	   *lst;		/* Add subplan to subplans list */		results->subplans = lappend(results->subplans, subplan);		/* Check extParam list for params to add to paramids */		foreach(lst, subplan->plan->extParam)		{			int			paramid = lfirsti(lst);			Var		   *var = nth(paramid, PlannerParamVar);			/* note varlevelsup is absolute level number */			if (var->varlevelsup < PlannerQueryLevel &&				! intMember(paramid, results->paramids))				results->paramids = lconsi(paramid, results->paramids);		}		/* XXX We do NOT allow expression_tree_walker to examine the args		 * passed to the subplan.  Is that correct???  It's what the		 * old code did, but it seems mighty bogus...  tgl 7/14/99		 */		return false;			/* don't recurse into subplan args */	}	return expression_tree_walker(node, finalize_primnode_walker,								  (void *) results);}/* Replace correlation vars (uplevel vars) with Params. *//* XXX should replace this with use of a generalized tree rebuilder, * designed along the same lines as expression_tree_walker. * Not done yet. */Node *SS_replace_correlation_vars(Node *expr){	if (expr == NULL)		return NULL;	if (IsA(expr, Var))	{		if (((Var *) expr)->varlevelsup > 0)			expr = (Node *) _replace_var((Var *) expr);	}	else if (single_node(expr))		return expr;	else if (IsA(expr, List))	{		List	   *le;		foreach(le, (List *) expr)			lfirst(le) = SS_replace_correlation_vars((Node *) lfirst(le));	}	else if (IsA(expr, Expr))	{		/* XXX do we need to do anything special with subplans? */		((Expr *) expr)->args = (List *)			SS_replace_correlation_vars((Node *) ((Expr *) expr)->args);	}	else if (IsA(expr, Aggref))		((Aggref *) expr)->target = SS_replace_correlation_vars(((Aggref *) expr)->target);	else if (IsA(expr, Iter))		((Iter *) expr)->iterexpr = SS_replace_correlation_vars(((Iter *) expr)->iterexpr);	else if (IsA(expr, ArrayRef))	{		((ArrayRef *) expr)->refupperindexpr = (List *)			SS_replace_correlation_vars((Node *) ((ArrayRef *) expr)->refupperindexpr);		((ArrayRef *) expr)->reflowerindexpr = (List *)			SS_replace_correlation_vars((Node *) ((ArrayRef *) expr)->reflowerindexpr);		((ArrayRef *) expr)->refexpr = SS_replace_correlation_vars(((ArrayRef *) expr)->refexpr);		((ArrayRef *) expr)->refassgnexpr = SS_replace_correlation_vars(((ArrayRef *) expr)->refassgnexpr);	}	else if (IsA(expr, CaseExpr))	{		CaseExpr   *caseexpr = (CaseExpr *) expr;		List	   *le;		foreach(le, caseexpr->args)		{			CaseWhen   *when = (CaseWhen *) lfirst(le);			Assert(IsA(when, CaseWhen));			when->expr = SS_replace_correlation_vars(when->expr);			when->result = SS_replace_correlation_vars(when->result);		}		/* caseexpr->arg should be null, but we'll check it anyway */		caseexpr->arg = SS_replace_correlation_vars(caseexpr->arg);		caseexpr->defresult = SS_replace_correlation_vars(caseexpr->defresult);	}	else if (IsA(expr, TargetEntry))		((TargetEntry *) expr)->expr = SS_replace_correlation_vars(((TargetEntry *) expr)->expr);	else if (IsA(expr, SubLink))	{		List	   *le;		foreach(le, ((SubLink *) expr)->oper)	/* left sides only */		{			List	   *oparg = ((Expr *) lfirst(le))->args;			lfirst(oparg) = (List *)				SS_replace_correlation_vars((Node *) lfirst(oparg));		}		((SubLink *) expr)->lefthand = (List *)			SS_replace_correlation_vars((Node *) ((SubLink *) expr)->lefthand);	}	else		elog(ERROR, "SS_replace_correlation_vars: can't handle node %d",			 nodeTag(expr));	return expr;}/* Replace sublinks by subplans in the given expression *//* XXX should replace this with use of a generalized tree rebuilder, * designed along the same lines as expression_tree_walker. * Not done yet. */Node *SS_process_sublinks(Node *expr){	if (expr == NULL)		return NULL;	if (IsA(expr, SubLink))	{		expr = _make_subplan((SubLink *) expr);	}	else if (single_node(expr))		return expr;	else if (IsA(expr, List))	{		List	   *le;		foreach(le, (List *) expr)			lfirst(le) = SS_process_sublinks((Node *) lfirst(le));	}	else if (IsA(expr, Expr))	{		/* We should never see a subplan node here, since this is the		 * routine that makes 'em in the first place.  No need to check.		 */		((Expr *) expr)->args = (List *)			SS_process_sublinks((Node *) ((Expr *) expr)->args);	}	else if (IsA(expr, Aggref))		((Aggref *) expr)->target = SS_process_sublinks(((Aggref *) expr)->target);	else if (IsA(expr, Iter))		((Iter *) expr)->iterexpr = SS_process_sublinks(((Iter *) expr)->iterexpr);	else if (IsA(expr, ArrayRef))	{		((ArrayRef *) expr)->refupperindexpr = (List *)			SS_process_sublinks((Node *) ((ArrayRef *) expr)->refupperindexpr);		((ArrayRef *) expr)->reflowerindexpr = (List *)			SS_process_sublinks((Node *) ((ArrayRef *) expr)->reflowerindexpr);		((ArrayRef *) expr)->refexpr = SS_process_sublinks(((ArrayRef *) expr)->refexpr);		((ArrayRef *) expr)->refassgnexpr = SS_process_sublinks(((ArrayRef *) expr)->refassgnexpr);	}	else if (IsA(expr, CaseExpr))	{		CaseExpr   *caseexpr = (CaseExpr *) expr;		List	   *le;		foreach(le, caseexpr->args)		{			CaseWhen   *when = (CaseWhen *) lfirst(le);			Assert(IsA(when, CaseWhen));			when->expr = SS_process_sublinks(when->expr);			when->result = SS_process_sublinks(when->result);		}		/* caseexpr->arg should be null, but we'll check it anyway */		caseexpr->arg = SS_process_sublinks(caseexpr->arg);		caseexpr->defresult = SS_process_sublinks(caseexpr->defresult);	}	else		elog(ERROR, "SS_process_sublinks: can't handle node %d",			 nodeTag(expr));	return expr;}List *SS_finalize_plan(Plan *plan){	List	   *extParam = NIL;	List	   *locParam = NIL;	finalize_primnode_results results;	List	   *lst;	if (plan == NULL)		return NULL;	/* Find params in targetlist, make sure there are no subplans there */	finalize_primnode((Node *) plan->targetlist, &results);	Assert(results.subplans == NIL);	/* From here on, we invoke finalize_primnode_walker not finalize_primnode,	 * so that results.paramids lists are automatically merged together and	 * we don't have to do it the hard way.  But when recursing to self,	 * we do have to merge the lists.  Oh well.	 */	switch (nodeTag(plan))	{		case T_Result:			finalize_primnode_walker(((Result *) plan)->resconstantqual,									 &results);			/* results.subplans is NOT necessarily empty here ... */			break;		case T_Append:			foreach(lst, ((Append *) plan)->appendplans)				results.paramids = set_unioni(results.paramids,								SS_finalize_plan((Plan *) lfirst(lst)));			break;		case T_IndexScan:			finalize_primnode_walker((Node *) ((IndexScan *) plan)->indxqual,									 &results);			Assert(results.subplans == NIL);			break;		case T_MergeJoin:			finalize_primnode_walker((Node *) ((MergeJoin *) plan)->mergeclauses,									 &results);			Assert(results.subplans == NIL);			break;		case T_HashJoin:			finalize_primnode_walker((Node *) ((HashJoin *) plan)->hashclauses,									 &results);			Assert(results.subplans == NIL);			break;		case T_Hash:			finalize_primnode_walker((Node *) ((Hash *) plan)->hashkey,									 &results);			Assert(results.subplans == NIL);			break;		case T_Agg:			finalize_primnode_walker((Node *) ((Agg *) plan)->aggs,									 &results);			Assert(results.subplans == NIL);			break;		case T_SeqScan:		case T_NestLoop:		case T_Material:		case T_Sort:		case T_Unique:		case T_Group:			break;		default:			elog(ERROR, "SS_finalize_plan: node %d unsupported",				 nodeTag(plan));			return NULL;	}	finalize_primnode_walker((Node *) plan->qual, &results);	/* subplans are OK in the qual... */	results.paramids = set_unioni(results.paramids,								  SS_finalize_plan(plan->lefttree));	results.paramids = set_unioni(results.paramids,								  SS_finalize_plan(plan->righttree));	/* Now we have all the paramids and subplans */	foreach(lst, results.paramids)	{		Var		   *var = nth(lfirsti(lst), PlannerParamVar);		/* note varlevelsup is absolute level number */		if (var->varlevelsup < PlannerQueryLevel)			extParam = lappendi(extParam, lfirsti(lst));		else if (var->varlevelsup > PlannerQueryLevel)			elog(ERROR, "SS_finalize_plan: plan shouldn't reference subplan's variable");		else		{			Assert(var->varno == 0 && var->varattno == 0);			locParam = lappendi(locParam, lfirsti(lst));		}	}	plan->extParam = extParam;	plan->locParam = locParam;	plan->subPlan = results.subplans;	return results.paramids;}/* Construct a list of all subplans found within the given node tree */static bool SS_pull_subplan_walker(Node *node, List **listptr);List *SS_pull_subplan(Node *expr){	List	   *result = NIL;	SS_pull_subplan_walker(expr, &result);	return result;}static boolSS_pull_subplan_walker(Node *node, List **listptr){	if (node == NULL)		return false;	if (is_subplan(node))	{		*listptr = lappend(*listptr, ((Expr *) node)->oper);		/* XXX original code did not examine args to subplan, is this right? */		return false;	}	return expression_tree_walker(node, SS_pull_subplan_walker,								  (void *) listptr);}

⌨️ 快捷键说明

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