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

📄 nodesubplan.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * nodeSubplan.c *	  routines to support subselects * *------------------------------------------------------------------------- *//* *	 INTERFACE ROUTINES *		ExecSubPlan  - process a subselect *		ExecInitSubPlan - initialize a subselect *		ExecEndSubPlan	- shut down a subselect */#include "postgres.h"#include "access/heapam.h"#include "tcop/pquery.h"#include "executor/executor.h"#include "executor/execdebug.h"#include "executor/nodeSubplan.h"/* ---------------------------------------------------------------- *		ExecSubPlan(node) * * ---------------------------------------------------------------- */DatumExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext){	Plan	   *plan = node->plan;	SubLink    *sublink = node->sublink;	SubLinkType subLinkType = sublink->subLinkType;	TupleTableSlot *slot;	List	   *lst;	Datum		result = (Datum) false;	bool		found = false;	/* TRUE if got at least one subplan tuple */	if (node->setParam != NULL)		elog(ERROR, "ExecSubPlan: can't set parent params from subquery");	/*	 * Set Params of this plan from parent plan correlation Vars	 */	if (node->parParam != NULL)	{		foreach(lst, node->parParam)		{			ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);			prm->value = ExecEvalExpr((Node *) lfirst(pvar),									  econtext,									  &(prm->isnull), NULL);			pvar = lnext(pvar);		}		plan->chgParam = nconc(plan->chgParam, listCopy(node->parParam));	}	ExecReScan(plan, (ExprContext *) NULL, plan);	/*	 * For all sublink types except EXPR_SUBLINK, the result type is	 * boolean, and we have a fairly clear idea of how to combine multiple	 * subitems and deal with NULL values or an empty subplan result.	 *	 * For EXPR_SUBLINK, the result type is whatever the combining operator	 * returns.  We have no way to deal with more than one column in the	 * subplan result --- hopefully the parser forbids that.  More	 * seriously, it's unclear what to do with NULL values or an empty	 * subplan result. For now, we error out, but should something else	 * happen?	 */	for (slot = ExecProcNode(plan, plan);		 !TupIsNull(slot);		 slot = ExecProcNode(plan, plan))	{		HeapTuple	tup = slot->val;		TupleDesc	tdesc = slot->ttc_tupleDescriptor;		int			i = 1;		if (subLinkType == EXPR_SUBLINK && found)		{			elog(ERROR, "ExecSubPlan: more than one tuple returned by expression subselect");			return (Datum) false;		}		if (subLinkType == EXISTS_SUBLINK)			return (Datum) true;		found = true;		foreach(lst, sublink->oper)		{			Expr	   *expr = (Expr *) lfirst(lst);			Const	   *con = lsecond(expr->args);			bool		isnull;			con->constvalue = heap_getattr(tup, i, tdesc, &(con->constisnull));			result = ExecEvalExpr((Node *) expr, econtext, &isnull, (bool *) NULL);			if (isnull)			{				if (subLinkType == EXPR_SUBLINK)					elog(ERROR, "ExecSubPlan: null value returned by expression subselect");				else					result = (Datum) false;			}			if (subLinkType != EXPR_SUBLINK)			{				if ((!(bool) result && !(sublink->useor)) ||					((bool) result && sublink->useor))					break;			}			i++;		}		if (subLinkType == ALL_SUBLINK && !(bool) result)			break;		if (subLinkType == ANY_SUBLINK && (bool) result)			break;	}	if (!found)	{		/* deal with empty subplan result.	Note default result is 'false' */		if (subLinkType == ALL_SUBLINK)			result = (Datum) true;		else if (subLinkType == EXPR_SUBLINK)			elog(ERROR, "ExecSubPlan: no tuples returned by expression subselect");	}	return result;}/* ---------------------------------------------------------------- *		ExecInitSubPlan * * ---------------------------------------------------------------- */extern void ExecCheckPerms(CmdType op, int resRel, List *rtable, Query *q);boolExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent){	EState	   *sp_estate = CreateExecutorState();	ExecCheckPerms(CMD_SELECT, 0, node->rtable, (Query *) NULL);	sp_estate->es_range_table = node->rtable;	sp_estate->es_param_list_info = estate->es_param_list_info;	sp_estate->es_param_exec_vals = estate->es_param_exec_vals;	sp_estate->es_tupleTable =		ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10);	pfree(sp_estate->es_refcount);	sp_estate->es_refcount = estate->es_refcount;	sp_estate->es_snapshot = estate->es_snapshot;	if (!ExecInitNode(node->plan, sp_estate, NULL))		return false;	node->shutdown = true;	/*	 * If this plan is un-correlated or undirect correlated one and want	 * to set params for parent plan then prepare parameters.	 */	if (node->setParam != NULL)	{		List	   *lst;		foreach(lst, node->setParam)		{			ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);			prm->execPlan = node;		}		/*		 * Note that in the case of un-correlated subqueries we don't care		 * about setting parent->chgParam here: indices take care about		 * it, for others - it doesn't matter...		 */	}	return true;}/* ---------------------------------------------------------------- *		ExecSetParamPlan * *		Executes plan of node and sets parameters. * ---------------------------------------------------------------- */voidExecSetParamPlan(SubPlan *node){	Plan	   *plan = node->plan;	SubLink    *sublink = node->sublink;	TupleTableSlot *slot;	List	   *lst;	bool		found = false;	if (sublink->subLinkType == ANY_SUBLINK ||		sublink->subLinkType == ALL_SUBLINK)		elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported");	if (plan->chgParam != NULL)		ExecReScan(plan, (ExprContext *) NULL, plan);	for (slot = ExecProcNode(plan, plan);		 !TupIsNull(slot);		 slot = ExecProcNode(plan, plan))	{		HeapTuple	tup = slot->val;		TupleDesc	tdesc = slot->ttc_tupleDescriptor;		int			i = 1;		if (sublink->subLinkType == EXPR_SUBLINK && found)		{			elog(ERROR, "ExecSetParamPlan: more than one tuple returned by expression subselect");			return;		}		found = true;		if (sublink->subLinkType == EXISTS_SUBLINK)		{			ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);			prm->execPlan = NULL;			prm->value = (Datum) true;			prm->isnull = false;			break;		}		/*		 * If this is uncorrelated subquery then its plan will be closed		 * (see below) and this tuple will be free-ed - bad for not byval		 * types... But is free-ing possible in the next ExecProcNode in		 * this loop ? Who knows... Someday we'll keep track of saved		 * tuples...		 */		tup = heap_copytuple(tup);		foreach(lst, node->setParam)		{			ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);			prm->execPlan = NULL;			prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));			i++;		}	}	if (!found)	{		if (sublink->subLinkType == EXISTS_SUBLINK)		{			ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);			prm->execPlan = NULL;			prm->value = (Datum) false;			prm->isnull = false;		}		else		{			foreach(lst, node->setParam)			{				ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);				prm->execPlan = NULL;				prm->value = (Datum) NULL;				prm->isnull = true;			}		}	}	if (plan->extParam == NULL) /* un-correlated ... */	{		ExecEndNode(plan, plan);		node->shutdown = false;	}}/* ---------------------------------------------------------------- *		ExecEndSubPlan * ---------------------------------------------------------------- */voidExecEndSubPlan(SubPlan *node){	if (node->shutdown)	{		ExecEndNode(node->plan, node->plan);		node->shutdown = false;	}}voidExecReScanSetParamPlan(SubPlan *node, Plan *parent){	Plan	   *plan = node->plan;	List	   *lst;	if (node->parParam != NULL)		elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet");	if (node->setParam == NULL)		elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL");	if (plan->extParam == NULL)		elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");	/*	 * Don't actual re-scan: ExecSetParamPlan does re-scan if	 * node->plan->chgParam is not NULL... ExecReScan (plan, NULL, plan);	 */	foreach(lst, node->setParam)	{		ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);		prm->execPlan = node;	}	parent->chgParam = nconc(parent->chgParam, listCopy(node->setParam));}

⌨️ 快捷键说明

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