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

📄 nodesubplan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*	 * If this plan is un-correlated or undirect correlated one and want to	 * set params for parent plan then mark parameters as needing evaluation.	 *	 * 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...	 */	if (subplan->setParam != NIL)	{		ListCell   *lst;		foreach(lst, subplan->setParam)		{			int			paramid = lfirst_int(lst);			ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);			prm->execPlan = node;		}	}	/*	 * If we are going to hash the subquery output, initialize relevant stuff.	 * (We don't create the hashtable until needed, though.)	 */	if (subplan->useHashTable)	{		int			ncols,					i;		TupleDesc	tupDesc;		TupleTable	tupTable;		TupleTableSlot *slot;		List	   *lefttlist,				   *righttlist,				   *leftptlist,				   *rightptlist;		ListCell   *lexpr;		/* We need a memory context to hold the hash table(s) */		node->tablecxt =			AllocSetContextCreate(CurrentMemoryContext,								  "Subplan HashTable Context",								  ALLOCSET_DEFAULT_MINSIZE,								  ALLOCSET_DEFAULT_INITSIZE,								  ALLOCSET_DEFAULT_MAXSIZE);		/* and a short-lived exprcontext for function evaluation */		node->innerecontext = CreateExprContext(estate);		/* Silly little array of column numbers 1..n */		ncols = list_length(node->exprs);		node->keyColIdx = (AttrNumber *) palloc(ncols * sizeof(AttrNumber));		for (i = 0; i < ncols; i++)			node->keyColIdx[i] = i + 1;		/*		 * We use ExecProject to evaluate the lefthand and righthand		 * expression lists and form tuples.  (You might think that we could		 * use the sub-select's output tuples directly, but that is not the		 * case if we had to insert any run-time coercions of the sub-select's		 * output datatypes; anyway this avoids storing any resjunk columns		 * that might be in the sub-select's output.) Run through the		 * combining expressions to build tlists for the lefthand and		 * righthand sides.  We need both the ExprState list (for ExecProject)		 * and the underlying parse Exprs (for ExecTypeFromTL).		 *		 * We also extract the combining operators themselves to initialize		 * the equality and hashing functions for the hash tables.		 */		lefttlist = righttlist = NIL;		leftptlist = rightptlist = NIL;		node->eqfunctions = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));		node->hashfunctions = (FmgrInfo *) palloc(ncols * sizeof(FmgrInfo));		i = 1;		foreach(lexpr, node->exprs)		{			FuncExprState *fstate = (FuncExprState *) lfirst(lexpr);			OpExpr	   *opexpr = (OpExpr *) fstate->xprstate.expr;			ExprState  *exstate;			Expr	   *expr;			TargetEntry *tle;			GenericExprState *tlestate;			Oid			hashfn;			Assert(IsA(fstate, FuncExprState));			Assert(IsA(opexpr, OpExpr));			Assert(list_length(fstate->args) == 2);			/* Process lefthand argument */			exstate = (ExprState *) linitial(fstate->args);			expr = exstate->expr;			tle = makeTargetEntry(expr,								  i,								  NULL,								  false);			tlestate = makeNode(GenericExprState);			tlestate->xprstate.expr = (Expr *) tle;			tlestate->xprstate.evalfunc = NULL;			tlestate->arg = exstate;			lefttlist = lappend(lefttlist, tlestate);			leftptlist = lappend(leftptlist, tle);			/* Process righthand argument */			exstate = (ExprState *) lsecond(fstate->args);			expr = exstate->expr;			tle = makeTargetEntry(expr,								  i,								  NULL,								  false);			tlestate = makeNode(GenericExprState);			tlestate->xprstate.expr = (Expr *) tle;			tlestate->xprstate.evalfunc = NULL;			tlestate->arg = exstate;			righttlist = lappend(righttlist, tlestate);			rightptlist = lappend(rightptlist, tle);			/* Lookup the combining function */			fmgr_info(opexpr->opfuncid, &node->eqfunctions[i - 1]);			node->eqfunctions[i - 1].fn_expr = (Node *) opexpr;			/* Lookup the associated hash function */			hashfn = get_op_hash_function(opexpr->opno);			if (!OidIsValid(hashfn))				elog(ERROR, "could not find hash function for hash operator %u",					 opexpr->opno);			fmgr_info(hashfn, &node->hashfunctions[i - 1]);			i++;		}		/*		 * Create a tupletable to hold these tuples.  (Note: we never bother		 * to free the tupletable explicitly; that's okay because it will		 * never store raw disk tuples that might have associated buffer pins.		 * The only resource involved is memory, which will be cleaned up by		 * freeing the query context.)		 */		tupTable = ExecCreateTupleTable(2);		/*		 * Construct tupdescs, slots and projection nodes for left and right		 * sides.  The lefthand expressions will be evaluated in the parent		 * plan node's exprcontext, which we don't have access to here.		 * Fortunately we can just pass NULL for now and fill it in later		 * (hack alert!).  The righthand expressions will be evaluated in our		 * own innerecontext.		 */		tupDesc = ExecTypeFromTL(leftptlist, false);		slot = ExecAllocTableSlot(tupTable);		ExecSetSlotDescriptor(slot, tupDesc, true);		node->projLeft = ExecBuildProjectionInfo(lefttlist,												 NULL,												 slot);		tupDesc = ExecTypeFromTL(rightptlist, false);		slot = ExecAllocTableSlot(tupTable);		ExecSetSlotDescriptor(slot, tupDesc, true);		node->projRight = ExecBuildProjectionInfo(righttlist,												  node->innerecontext,												  slot);	}}/* ---------------------------------------------------------------- *		ExecSetParamPlan * *		Executes an InitPlan subplan and sets its output parameters. * * This is called from ExecEvalParam() when the value of a PARAM_EXEC * parameter is requested and the param's execPlan field is set (indicating * that the param has not yet been evaluated).	This allows lazy evaluation * of initplans: we don't run the subplan until/unless we need its output. * Note that this routine MUST clear the execPlan fields of the plan's * output parameters after evaluating them! * ---------------------------------------------------------------- */voidExecSetParamPlan(SubPlanState *node, ExprContext *econtext){	SubPlan    *subplan = (SubPlan *) node->xprstate.expr;	PlanState  *planstate = node->planstate;	SubLinkType subLinkType = subplan->subLinkType;	MemoryContext oldcontext;	TupleTableSlot *slot;	ListCell   *l;	bool		found = false;	ArrayBuildState *astate = NULL;	/*	 * Must switch to child query's per-query memory context.	 */	oldcontext = MemoryContextSwitchTo(node->sub_estate->es_query_cxt);	if (subLinkType == ANY_SUBLINK ||		subLinkType == ALL_SUBLINK)		elog(ERROR, "ANY/ALL subselect unsupported as initplan");	if (planstate->chgParam != NULL)		ExecReScan(planstate, NULL);	for (slot = ExecProcNode(planstate);		 !TupIsNull(slot);		 slot = ExecProcNode(planstate))	{		TupleDesc	tdesc = slot->tts_tupleDescriptor;		int			i = 1;		if (subLinkType == EXISTS_SUBLINK)		{			/* There can be only one param... */			int			paramid = linitial_int(subplan->setParam);			ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);			prm->execPlan = NULL;			prm->value = BoolGetDatum(true);			prm->isnull = false;			found = true;			break;		}		if (subLinkType == ARRAY_SUBLINK)		{			Datum		dvalue;			bool		disnull;			found = true;			/* stash away current value */			dvalue = slot_getattr(slot, 1, &disnull);			astate = accumArrayResult(astate, dvalue, disnull,									  tdesc->attrs[0]->atttypid,									  oldcontext);			/* keep scanning subplan to collect all values */			continue;		}		if (found &&			(subLinkType == EXPR_SUBLINK ||			 subLinkType == MULTIEXPR_SUBLINK))			ereport(ERROR,					(errcode(ERRCODE_CARDINALITY_VIOLATION),					 errmsg("more than one row returned by a subquery used as an expression")));		found = true;		/*		 * We need to copy the subplan's tuple into our own context, in case		 * any of the params are pass-by-ref type --- the pointers stored in		 * the param structs will point at this copied tuple! node->curTuple		 * keeps track of the copied tuple for eventual freeing.		 */		MemoryContextSwitchTo(econtext->ecxt_per_query_memory);		if (node->curTuple)			heap_freetuple(node->curTuple);		node->curTuple = ExecCopySlotTuple(slot);		MemoryContextSwitchTo(node->sub_estate->es_query_cxt);		/*		 * Now set all the setParam params from the columns of the tuple		 */		foreach(l, subplan->setParam)		{			int			paramid = lfirst_int(l);			ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);			prm->execPlan = NULL;			prm->value = heap_getattr(node->curTuple, i, tdesc,									  &(prm->isnull));			i++;		}	}	if (!found)	{		if (subLinkType == EXISTS_SUBLINK)		{			/* There can be only one param... */			int			paramid = linitial_int(subplan->setParam);			ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);			prm->execPlan = NULL;			prm->value = BoolGetDatum(false);			prm->isnull = false;		}		else		{			foreach(l, subplan->setParam)			{				int			paramid = lfirst_int(l);				ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);				prm->execPlan = NULL;				prm->value = (Datum) 0;				prm->isnull = true;			}		}	}	else if (subLinkType == ARRAY_SUBLINK)	{		/* There can be only one param... */		int			paramid = linitial_int(subplan->setParam);		ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);		Assert(astate != NULL);		prm->execPlan = NULL;		/* We build the result in query context so it won't disappear */		prm->value = makeArrayResult(astate, econtext->ecxt_per_query_memory);		prm->isnull = false;	}	MemoryContextSwitchTo(oldcontext);}/* ---------------------------------------------------------------- *		ExecEndSubPlan * ---------------------------------------------------------------- */voidExecEndSubPlan(SubPlanState *node){	if (node->needShutdown)	{		MemoryContext oldcontext;		oldcontext = MemoryContextSwitchTo(node->sub_estate->es_query_cxt);		ExecEndPlan(node->planstate, node->sub_estate);		MemoryContextSwitchTo(oldcontext);		FreeExecutorState(node->sub_estate);		node->sub_estate = NULL;		node->planstate = NULL;		node->needShutdown = false;	}}/* * Mark an initplan as needing recalculation */voidExecReScanSetParamPlan(SubPlanState *node, PlanState *parent){	PlanState  *planstate = node->planstate;	SubPlan    *subplan = (SubPlan *) node->xprstate.expr;	EState	   *estate = parent->state;	ListCell   *l;	/* sanity checks */	if (subplan->parParam != NIL)		elog(ERROR, "direct correlated subquery unsupported as initplan");	if (subplan->setParam == NIL)		elog(ERROR, "setParam list of initplan is empty");	if (bms_is_empty(planstate->plan->extParam))		elog(ERROR, "extParam set of initplan is empty");	/*	 * Don't actually re-scan: ExecSetParamPlan does it if needed.	 */	/*	 * Mark this subplan's output parameters as needing recalculation	 */	foreach(l, subplan->setParam)	{		int			paramid = lfirst_int(l);		ParamExecData *prm = &(estate->es_param_exec_vals[paramid]);		prm->execPlan = node;		parent->chgParam = bms_add_member(parent->chgParam, paramid);	}}

⌨️ 快捷键说明

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