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

📄 nodesubplan.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (subplan->setParam != NIL)	{		List	   *lst;		foreach(lst, subplan->setParam)		{			int			paramid = lfirsti(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,				   *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 = 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(length(fstate->args) == 2);			/* Process lefthand argument */			exstate = (ExprState *) lfirst(fstate->args);			expr = exstate->expr;			tle = makeTargetEntry(makeResdom(i,											 exprType((Node *) expr),											 exprTypmod((Node *) expr),											 NULL,											 false),								  expr);			tlestate = makeNode(GenericExprState);			tlestate->xprstate.expr = (Expr *) tle;			tlestate->arg = exstate;			lefttlist = lappend(lefttlist, tlestate);			leftptlist = lappend(leftptlist, tle);			/* Process righthand argument */			exstate = (ExprState *) lsecond(fstate->args);			expr = exstate->expr;			tle = makeTargetEntry(makeResdom(i,											 exprType((Node *) expr),											 exprTypmod((Node *) expr),											 NULL,											 false),								  expr);			tlestate = makeNode(GenericExprState);			tlestate->xprstate.expr = (Expr *) tle;			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;	List	   *lst;	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))	{		HeapTuple	tup = slot->val;		TupleDesc	tdesc = slot->ttc_tupleDescriptor;		int			i = 1;		if (subLinkType == EXISTS_SUBLINK)		{			/* There can be only one param... */			int			paramid = lfirsti(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 = heap_getattr(tup, 1, tdesc, &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);		tup = heap_copytuple(tup);		if (node->curTuple)			heap_freetuple(node->curTuple);		node->curTuple = tup;		MemoryContextSwitchTo(node->sub_estate->es_query_cxt);		/*		 * Now set all the setParam params from the columns of the tuple		 */		foreach(lst, subplan->setParam)		{			int			paramid = lfirsti(lst);			ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);			prm->execPlan = NULL;			prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));			i++;		}	}	if (!found)	{		if (subLinkType == EXISTS_SUBLINK)		{			/* There can be only one param... */			int			paramid = lfirsti(subplan->setParam);			ParamExecData *prm = &(econtext->ecxt_param_exec_vals[paramid]);			prm->execPlan = NULL;			prm->value = BoolGetDatum(false);			prm->isnull = false;		}		else		{			foreach(lst, subplan->setParam)			{				int			paramid = lfirsti(lst);				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 = lfirsti(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;	List	   *lst;	/* 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(lst, subplan->setParam)	{		int			paramid = lfirsti(lst);		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 + -