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

📄 nodegroup.c

📁 PostgreSQL7.4.6 for Linux
💻 C
字号:
/*------------------------------------------------------------------------- * * nodeGroup.c *	  Routines to handle group nodes (used for queries with GROUP BY clause). * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * DESCRIPTION *	  The Group node is designed for handling queries with a GROUP BY clause. *	  Its outer plan must deliver tuples that are sorted in the order *	  specified by the grouping columns (ie. tuples from the same group are *	  consecutive).  That way, we just have to compare adjacent tuples to *	  locate group boundaries. * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.56 2003/08/04 02:39:59 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/heapam.h"#include "executor/executor.h"#include "executor/nodeGroup.h"/* *	 ExecGroup - * *		Return one tuple for each group of matching input tuples. */TupleTableSlot *ExecGroup(GroupState *node){	EState	   *estate;	ExprContext *econtext;	TupleDesc	tupdesc;	int			numCols;	AttrNumber *grpColIdx;	HeapTuple	outerTuple = NULL;	HeapTuple	firsttuple;	TupleTableSlot *outerslot;	ProjectionInfo *projInfo;	TupleTableSlot *resultSlot;	/*	 * get state info from node	 */	if (node->grp_done)		return NULL;	estate = node->ss.ps.state;	econtext = node->ss.ps.ps_ExprContext;	tupdesc = ExecGetScanType(&node->ss);	numCols = ((Group *) node->ss.ps.plan)->numCols;	grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;	/*	 * We need not call ResetExprContext here because execTuplesMatch will	 * reset the per-tuple memory context once per input tuple.	 */	/* If we don't already have first tuple of group, fetch it */	/* this should occur on the first call only */	firsttuple = node->grp_firstTuple;	if (firsttuple == NULL)	{		outerslot = ExecProcNode(outerPlanState(node));		if (TupIsNull(outerslot))		{			node->grp_done = TRUE;			return NULL;		}		node->grp_firstTuple = firsttuple =			heap_copytuple(outerslot->val);	}	/*	 * Scan over all tuples that belong to this group	 */	for (;;)	{		outerslot = ExecProcNode(outerPlanState(node));		if (TupIsNull(outerslot))		{			node->grp_done = TRUE;			outerTuple = NULL;			break;		}		outerTuple = outerslot->val;		/*		 * Compare with first tuple and see if this tuple is of the same		 * group.		 */		if (!execTuplesMatch(firsttuple, outerTuple,							 tupdesc,							 numCols, grpColIdx,							 node->eqfunctions,							 econtext->ecxt_per_tuple_memory))			break;	}	/*	 * form a projection tuple based on the (copied) first tuple of the	 * group, and store it in the result tuple slot.	 */	ExecStoreTuple(firsttuple,				   node->ss.ss_ScanTupleSlot,				   InvalidBuffer,				   false);	econtext->ecxt_scantuple = node->ss.ss_ScanTupleSlot;	projInfo = node->ss.ps.ps_ProjInfo;	resultSlot = ExecProject(projInfo, NULL);	/* save first tuple of next group, if we are not done yet */	if (!node->grp_done)	{		heap_freetuple(firsttuple);		node->grp_firstTuple = heap_copytuple(outerTuple);	}	return resultSlot;}/* ----------------- * ExecInitGroup * *	Creates the run-time information for the group node produced by the *	planner and initializes its outer subtree * ----------------- */GroupState *ExecInitGroup(Group *node, EState *estate){	GroupState *grpstate;	/*	 * create state structure	 */	grpstate = makeNode(GroupState);	grpstate->ss.ps.plan = (Plan *) node;	grpstate->ss.ps.state = estate;	grpstate->grp_firstTuple = NULL;	grpstate->grp_done = FALSE;	/*	 * create expression context	 */	ExecAssignExprContext(estate, &grpstate->ss.ps);#define GROUP_NSLOTS 2	/*	 * tuple table initialization	 */	ExecInitScanTupleSlot(estate, &grpstate->ss);	ExecInitResultTupleSlot(estate, &grpstate->ss.ps);	/*	 * initialize child expressions	 */	grpstate->ss.ps.targetlist = (List *)		ExecInitExpr((Expr *) node->plan.targetlist,					 (PlanState *) grpstate);	grpstate->ss.ps.qual = (List *)		ExecInitExpr((Expr *) node->plan.qual,					 (PlanState *) grpstate);	/*	 * initialize child nodes	 */	outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate);	/*	 * initialize tuple type.	 */	ExecAssignScanTypeFromOuterPlan(&grpstate->ss);	/*	 * Initialize result tuple type and projection info.	 */	ExecAssignResultTypeFromTL(&grpstate->ss.ps);	ExecAssignProjectionInfo(&grpstate->ss.ps);	/*	 * Precompute fmgr lookup data for inner loop	 */	grpstate->eqfunctions =		execTuplesMatchPrepare(ExecGetScanType(&grpstate->ss),							   node->numCols,							   node->grpColIdx);	return grpstate;}intExecCountSlotsGroup(Group *node){	return ExecCountSlotsNode(outerPlan(node)) + GROUP_NSLOTS;}/* ------------------------ *		ExecEndGroup(node) * * ----------------------- */voidExecEndGroup(GroupState *node){	PlanState  *outerPlan;	ExecFreeExprContext(&node->ss.ps);	/* clean up tuple table */	ExecClearTuple(node->ss.ss_ScanTupleSlot);	outerPlan = outerPlanState(node);	ExecEndNode(outerPlan);}voidExecReScanGroup(GroupState *node, ExprContext *exprCtxt){	node->grp_done = FALSE;	if (node->grp_firstTuple != NULL)	{		heap_freetuple(node->grp_firstTuple);		node->grp_firstTuple = NULL;	}	if (((PlanState *) node)->lefttree &&		((PlanState *) node)->lefttree->chgParam == NULL)		ExecReScan(((PlanState *) node)->lefttree, exprCtxt);}

⌨️ 快捷键说明

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