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

📄 nodeagg.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
					}					else					{						/*						 * apply the transition functions.						 */						args[0] = value1[aggno];						args[1] = newVal;						value1[aggno] = (Datum) fmgr_c(&aggfns->xfn1,										  (FmgrValues *) args, &isNull1);						Assert(!isNull1);					}				}				if (aggfns->xfn2.fn_addr != NULL)				{					args[0] = value2[aggno];					value2[aggno] = (Datum) fmgr_c(&aggfns->xfn2,										  (FmgrValues *) args, &isNull2);					Assert(!isNull2);				}			}			/*			 * keep this for the projection (we only need one of these -			 * all the tuples we aggregate over share the same group			 * column)			 */			if (!oneTuple)				oneTuple = heap_copytuple(outerslot->val);			nTuplesAgged++;		}		/* --------------		 * finalize the aggregate (if necessary), and get the resultant value		 * --------------		 */		aggno = -1;		foreach(alist, node->aggs)		{			char	   *args[2];			AggFuncInfo *aggfns = &aggFuncInfo[++aggno];			if (noInitValue[aggno])			{				/*				 * No values found for this agg; return current state.				 * This seems to fix behavior for avg() aggregate. -tgl				 * 12/96				 */			}			else if (aggfns->finalfn.fn_addr != NULL && nTuplesAgged > 0)			{				if (aggfns->finalfn.fn_nargs > 1)				{					args[0] = (char *) value1[aggno];					args[1] = (char *) value2[aggno];				}				else if (aggfns->xfn1.fn_addr != NULL)					args[0] = (char *) value1[aggno];				else if (aggfns->xfn2.fn_addr != NULL)					args[0] = (char *) value2[aggno];				else					elog(NOTICE, "ExecAgg: no valid transition functions??");				value1[aggno] = (Datum) fmgr_c(&aggfns->finalfn,								   (FmgrValues *) args, &(nulls[aggno]));			}			else if (aggfns->xfn1.fn_addr != NULL)			{				/*				 * value in the right place, ignore. (If you remove this				 * case, fix the else part. -ay 2/95)				 */			}			else if (aggfns->xfn2.fn_addr != NULL)				value1[aggno] = value2[aggno];			else				elog(ERROR, "ExecAgg: no valid transition functions??");		}		/*		 * whether the aggregation is done depends on whether we are doing		 * aggregation over groups or the entire table		 */		if (nodeTag(outerPlan) == T_Group)		{			/* aggregation over groups */			aggstate->agg_done = ((Group *) outerPlan)->grpstate->grp_done;		}		else			aggstate->agg_done = TRUE;		/* ----------------		 *	form a projection tuple, store it in the result tuple		 *	slot and return it.		 * ----------------		 */		ExecStoreTuple(oneTuple,					   aggstate->csstate.css_ScanTupleSlot,					   InvalidBuffer,					   false);		econtext->ecxt_scantuple = aggstate->csstate.css_ScanTupleSlot;		resultSlot = ExecProject(projInfo, &isDone);		/*		 * As long as the retrieved group does not match the		 * qualifications it is ignored and the next group is fetched		 */		if (node->plan.qual != NULL)			qual_result = ExecQual(fix_opids(node->plan.qual), econtext);		else			qual_result = false;		if (oneTuple)			pfree(oneTuple);	}	while (node->plan.qual != NULL && qual_result != true);	return resultSlot;}/* ----------------- * ExecInitAgg * *	Creates the run-time information for the agg node produced by the *	planner and initializes its outer subtree * ----------------- */boolExecInitAgg(Agg *node, EState *estate, Plan *parent){	AggState   *aggstate;	Plan	   *outerPlan;	ExprContext *econtext;	/*	 * assign the node's execution state	 */	node->plan.state = estate;	/*	 * create state structure	 */	aggstate = makeNode(AggState);	node->aggstate = aggstate;	aggstate->agg_done = FALSE;	/*	 * assign node's base id and create expression context	 */	ExecAssignNodeBaseInfo(estate, &aggstate->csstate.cstate, (Plan *) parent);	ExecAssignExprContext(estate, &aggstate->csstate.cstate);#define AGG_NSLOTS 2	/*	 * tuple table initialization	 */	ExecInitScanTupleSlot(estate, &aggstate->csstate);	ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate);	econtext = aggstate->csstate.cstate.cs_ExprContext;	econtext->ecxt_values = (Datum *) palloc(sizeof(Datum) * length(node->aggs));	MemSet(econtext->ecxt_values, 0, sizeof(Datum) * length(node->aggs));	econtext->ecxt_nulls = (char *) palloc(sizeof(char) * length(node->aggs));	MemSet(econtext->ecxt_nulls, 0, sizeof(char) * length(node->aggs));	/*	 * initializes child nodes	 */	outerPlan = outerPlan(node);	ExecInitNode(outerPlan, estate, (Plan *) node);	/*	 * Result runs in its own context, but make it use our aggregates fix	 * for 'select sum(2+2)'	 */	if (nodeTag(outerPlan) == T_Result)	{		((Result *) outerPlan)->resstate->cstate.cs_ProjInfo->pi_exprContext->ecxt_values =			econtext->ecxt_values;		((Result *) outerPlan)->resstate->cstate.cs_ProjInfo->pi_exprContext->ecxt_nulls =			econtext->ecxt_nulls;	}	/* ----------------	 *	initialize tuple type.	 * ----------------	 */	ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate);	/*	 * Initialize tuple type for both result and scan. This node does no	 * projection	 */	ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate);	ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate);	return TRUE;}intExecCountSlotsAgg(Agg *node){	return ExecCountSlotsNode(outerPlan(node)) +	ExecCountSlotsNode(innerPlan(node)) +	AGG_NSLOTS;}/* ------------------------ *		ExecEndAgg(node) * * ----------------------- */voidExecEndAgg(Agg *node){	AggState   *aggstate;	Plan	   *outerPlan;	aggstate = node->aggstate;	ExecFreeProjectionInfo(&aggstate->csstate.cstate);	outerPlan = outerPlan(node);	ExecEndNode(outerPlan, (Plan *) node);	/* clean up tuple table */	ExecClearTuple(aggstate->csstate.css_ScanTupleSlot);}/***************************************************************************** *	Support Routines *****************************************************************************//* * aggGetAttr - *	  get the attribute (specified in the Var node in agg) to aggregate *	  over from the tuple */static DatumaggGetAttr(TupleTableSlot *slot,		   Aggref *aggref,		   bool *isNull){	Datum		result;	AttrNumber	attnum;	HeapTuple	heapTuple;	TupleDesc	tuple_type;	Buffer		buffer;	/* ----------------	 *	 extract tuple information from the slot	 * ----------------	 */	heapTuple = slot->val;	tuple_type = slot->ttc_tupleDescriptor;	buffer = slot->ttc_buffer;	attnum = ((Var *) aggref->target)->varattno;	/*	 * If the attribute number is invalid, then we are supposed to return	 * the entire tuple, we give back a whole slot so that callers know	 * what the tuple looks like.	 */	if (attnum == InvalidAttrNumber)	{		TupleTableSlot *tempSlot;		TupleDesc	td;		HeapTuple	tup;		tempSlot = makeNode(TupleTableSlot);		tempSlot->ttc_shouldFree = false;		tempSlot->ttc_descIsNew = true;		tempSlot->ttc_tupleDescriptor = (TupleDesc) NULL;		tempSlot->ttc_buffer = InvalidBuffer;		tempSlot->ttc_whichplan = -1;		tup = heap_copytuple(heapTuple);		td = CreateTupleDescCopy(slot->ttc_tupleDescriptor);		ExecSetSlotDescriptor(tempSlot, td);		ExecStoreTuple(tup, tempSlot, InvalidBuffer, true);		return (Datum) tempSlot;	}	result = heap_getattr(heapTuple,	/* tuple containing attribute */						  attnum,		/* attribute number of desired										 * attribute */						  tuple_type,	/* tuple descriptor of tuple */						  isNull);		/* return: is attribute null? */	/* ----------------	 *	return null if att is null	 * ----------------	 */	if (*isNull)		return (Datum) NULL;	return result;}voidExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent){	AggState   *aggstate = node->aggstate;	ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext;	aggstate->agg_done = FALSE;	MemSet(econtext->ecxt_values, 0, sizeof(Datum) * length(node->aggs));	MemSet(econtext->ecxt_nulls, 0, sizeof(char) * length(node->aggs));	/*	 * if chgParam of subnode is not null then plan will be re-scanned by	 * first ExecProcNode.	 */	if (((Plan *) node)->lefttree->chgParam == NULL)		ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);}

⌨️ 快捷键说明

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