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

📄 nodenestloop.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * nodeNestloop.c *	  routines to support nest-loop joins * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.11 1999/02/13 23:15:25 momjian Exp $ * *------------------------------------------------------------------------- *//* *	 INTERFACE ROUTINES *		ExecNestLoop	 - process a nestloop join of two plans *		ExecInitNestLoop - initialize the join *		ExecEndNestLoop  - shut down the join */#include "postgres.h"#include "executor/executor.h"#include "executor/execdebug.h"#include "executor/nodeNestloop.h"#include "executor/nodeIndexscan.h"/* ---------------------------------------------------------------- *		ExecNestLoop(node) * * old comments *		Returns the tuple joined from inner and outer tuples which *		satisfies the qualification clause. * *		It scans the inner relation to join with current outer tuple. * *		If none is found, next tuple form the outer relation is retrieved *		and the inner relation is scanned from the beginning again to join *		with the outer tuple. * *		Nil is returned if all the remaining outer tuples are tried and *		all fail to join with the inner tuples. * *		Nil is also returned if there is no tuple from inner realtion. * *		Conditions: *		  -- outerTuple contains current tuple from outer relation and *			 the right son(inner realtion) maintains "cursor" at the tuple *			 returned previously. *				This is achieved by maintaining a scan position on the outer *				relation. * *		Initial States: *		  -- the outer child and the inner child *			   are prepared to return the first tuple. * ---------------------------------------------------------------- */TupleTableSlot *ExecNestLoop(NestLoop *node, Plan *parent){	NestLoopState *nlstate;	Plan	   *innerPlan;	Plan	   *outerPlan;	bool		needNewOuterTuple;	TupleTableSlot *outerTupleSlot;	TupleTableSlot *innerTupleSlot;	List	   *qual;	bool		qualResult;	ExprContext *econtext;	/* ----------------	 *	get information from the node	 * ----------------	 */	ENL1_printf("getting info from node");	nlstate = node->nlstate;	qual = node->join.qual;	outerPlan = outerPlan(&node->join);	innerPlan = innerPlan(&node->join);	/* ----------------	 *	initialize expression context	 * ----------------	 */	econtext = nlstate->jstate.cs_ExprContext;	/* ----------------	 * get the current outer tuple	 * ----------------	 */	outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot;	econtext->ecxt_outertuple = outerTupleSlot;	/* ----------------	 *	Ok, everything is setup for the join so now loop until	 *	we return a qualifying join tuple..	 * ----------------	 */	if (nlstate->jstate.cs_TupFromTlist)	{		TupleTableSlot *result;		bool		isDone;		result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);		if (!isDone)			return result;	}	ENL1_printf("entering main loop");	for (;;)	{		/* ----------------		 *	The essential idea now is to get the next inner tuple		 *	and join it with the current outer tuple.		 * ----------------		 */		needNewOuterTuple = false;		if (!TupIsNull(outerTupleSlot))			ENL1_printf("have outer tuple, deal with it");		else		{			ENL1_printf("outer tuple is nil, need new outer tuple");			needNewOuterTuple = true;		}		/* ----------------		 *	if we have an outerTuple, try to get the next inner tuple.		 * ----------------		 */		if (!needNewOuterTuple)		{			ENL1_printf("getting new inner tuple");			innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);			econtext->ecxt_innertuple = innerTupleSlot;			if (TupIsNull(innerTupleSlot))			{				ENL1_printf("no inner tuple, need new outer tuple");				needNewOuterTuple = true;			}		}		/* ----------------		 *	loop until we have a new outer tuple and a new		 *	inner tuple.		 * ----------------		 */		while (needNewOuterTuple)		{			/* ----------------			 *	now try to get the next outer tuple			 * ----------------			 */			ENL1_printf("getting new outer tuple");			outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);			econtext->ecxt_outertuple = outerTupleSlot;			/* ----------------			 *	if there are no more outer tuples, then the join			 *	is complete..			 * ----------------			 */			if (TupIsNull(outerTupleSlot))			{				ENL1_printf("no outer tuple, ending join");				return NULL;			}			ENL1_printf("saving new outer tuple information");			nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot;			/* ----------------			 *	now rescan the inner plan and get a new inner tuple			 * ----------------			 */			ENL1_printf("rescanning inner plan");			/*			 * The scan key of the inner plan might depend on the current			 * outer tuple (e.g. in index scans), that's why we pass our			 * expr context.			 */			ExecReScan(innerPlan, econtext, parent);			ENL1_printf("getting new inner tuple");			innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);			econtext->ecxt_innertuple = innerTupleSlot;			if (TupIsNull(innerTupleSlot))				ENL1_printf("couldn't get inner tuple - need new outer tuple");			else			{				ENL1_printf("got inner and outer tuples");				needNewOuterTuple = false;			}		}						/* while (needNewOuterTuple) */		/* ----------------		 *	 at this point we have a new pair of inner and outer		 *	 tuples so we test the inner and outer tuples to see		 *	 if they satisify the node's qualification.		 * ----------------		 */		ENL1_printf("testing qualification");		qualResult = ExecQual((List *) qual, econtext);		if (qualResult)		{			/* ----------------			 *	qualification was satisified so we project and			 *	return the slot containing the result tuple			 *	using ExecProject().			 * ----------------			 */			ProjectionInfo *projInfo;			TupleTableSlot *result;			bool		isDone;			ENL1_printf("qualification succeeded, projecting tuple");			projInfo = nlstate->jstate.cs_ProjInfo;			result = ExecProject(projInfo, &isDone);			nlstate->jstate.cs_TupFromTlist = !isDone;			return result;		}		/* ----------------		 *	qualification failed so we have to try again..		 * ----------------		 */		ENL1_printf("qualification failed, looping");	}}/* ---------------------------------------------------------------- *		ExecInitNestLoop * *		Creates the run-time state information for the nestloop node *		produced by the planner and initailizes inner and outer relations *		(child nodes). * ---------------------------------------------------------------- */boolExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent){	NestLoopState *nlstate;	NL1_printf("ExecInitNestLoop: %s\n",			   "initializing node");	/* ----------------	 *	assign execution state to node	 * ----------------	 */	node->join.state = estate;	/* ----------------	 *	  create new nest loop state	 * ----------------	 */	nlstate = makeNode(NestLoopState);	nlstate->nl_PortalFlag = false;	node->nlstate = nlstate;	/* ----------------	 *	Miscellanious initialization	 *	 *		 +	assign node's base_id	 *		 +	assign debugging hooks and	 *		 +	create expression context for node	 * ----------------	 */	ExecAssignNodeBaseInfo(estate, &nlstate->jstate, parent);	ExecAssignExprContext(estate, &nlstate->jstate);#define NESTLOOP_NSLOTS 1	/* ----------------	 *	tuple table initialization	 * ----------------	 */	ExecInitResultTupleSlot(estate, &nlstate->jstate);	/* ----------------	 *	  now initialize children	 * ----------------	 */	ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);	ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);	/* ----------------	 *	initialize tuple type and projection info	 * ----------------	 */	ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate);	ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate);	/* ----------------	 *	finally, wipe the current outer tuple clean.	 * ----------------	 */	nlstate->jstate.cs_OuterTupleSlot = NULL;	nlstate->jstate.cs_TupFromTlist = false;	NL1_printf("ExecInitNestLoop: %s\n",			   "node initialized");	return TRUE;}intExecCountSlotsNestLoop(NestLoop *node){	return ExecCountSlotsNode(outerPlan(node)) +	ExecCountSlotsNode(innerPlan(node)) +	NESTLOOP_NSLOTS;}/* ---------------------------------------------------------------- *		ExecEndNestLoop * *		closes down scans and frees allocated storage * ---------------------------------------------------------------- */voidExecEndNestLoop(NestLoop *node){	NestLoopState *nlstate;	NL1_printf("ExecEndNestLoop: %s\n",			   "ending node processing");	/* ----------------	 *	get info from the node	 * ----------------	 */	nlstate = node->nlstate;	/* ----------------	 *	Free the projection info	 *	 *	Note: we don't ExecFreeResultType(nlstate)	 *		  because the rule manager depends on the tupType	 *		  returned by ExecMain().  So for now, this	 *		  is freed at end-transaction time.  -cim 6/2/91	 * ----------------	 */	ExecFreeProjectionInfo(&nlstate->jstate);	/* ----------------	 *	close down subplans	 * ----------------	 */	ExecEndNode(outerPlan((Plan *) node), (Plan *) node);	ExecEndNode(innerPlan((Plan *) node), (Plan *) node);	/* ----------------	 *	clean out the tuple table	 * ----------------	 */	ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot);	NL1_printf("ExecEndNestLoop: %s\n",			   "node processing ended");}/* ---------------------------------------------------------------- *		ExecReScanNestLoop * ---------------------------------------------------------------- */voidExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent){	NestLoopState *nlstate = node->nlstate;	Plan	   *outerPlan = outerPlan((Plan *) node);	/*	 * If outerPlan->chgParam is not null then plan will be automatically	 * re-scanned by first ExecProcNode. innerPlan is re-scanned for each	 * new outer tuple and MUST NOT be re-scanned from here or you'll get	 * troubles from inner index scans when outer Vars are used as	 * run-time keys...	 */	if (outerPlan->chgParam == NULL)		ExecReScan(outerPlan, exprCtxt, (Plan *) node);	/* let outerPlan to free its result typle ... */	nlstate->jstate.cs_OuterTupleSlot = NULL;	nlstate->jstate.cs_TupFromTlist = false;	return;}

⌨️ 快捷键说明

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