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

📄 nodemergejoin.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
			/* NULL > non-NULL */			result = 1;			break;		}		if (clause->risnull)		{			/* non-NULL < NULL */			result = -1;			break;		}		if (clause->cmpstrategy == MERGEFUNC_LT)		{			InitFunctionCallInfoData(fcinfo, &(clause->eqfinfo), 2,									 NULL, NULL);			fcinfo.arg[0] = clause->ldatum;			fcinfo.arg[1] = clause->rdatum;			fcinfo.argnull[0] = false;			fcinfo.argnull[1] = false;			fresult = FunctionCallInvoke(&fcinfo);			if (fcinfo.isnull)			{				nulleqnull = true;				continue;			}			else if (DatumGetBool(fresult))			{				/* equal */				continue;			}			InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,									 NULL, NULL);			fcinfo.arg[0] = clause->ldatum;			fcinfo.arg[1] = clause->rdatum;			fcinfo.argnull[0] = false;			fcinfo.argnull[1] = false;			fresult = FunctionCallInvoke(&fcinfo);			if (fcinfo.isnull)			{				nulleqnull = true;				continue;			}			else if (DatumGetBool(fresult))			{				/* less than */				result = -1;				break;			}			else			{				/* greater than */				result = 1;				break;			}		}		else			/* must be MERGEFUNC_CMP */		{			InitFunctionCallInfoData(fcinfo, &(clause->cmpfinfo), 2,									 NULL, NULL);			fcinfo.arg[0] = clause->ldatum;			fcinfo.arg[1] = clause->rdatum;			fcinfo.argnull[0] = false;			fcinfo.argnull[1] = false;			fresult = FunctionCallInvoke(&fcinfo);			if (fcinfo.isnull)			{				nulleqnull = true;				continue;			}			else if (DatumGetInt32(fresult) == 0)			{				/* equal */				continue;			}			else if (DatumGetInt32(fresult) < 0)			{				/* less than */				result = -1;				break;			}			else			{				/* greater than */				result = 1;				break;			}		}	}	/*	 * If we had any null comparison results or NULL-vs-NULL inputs, we do not	 * want to report that the tuples are equal.  Instead, if result is still	 * 0, change it to +1.	This will result in advancing the inner side of	 * the join.	 */	if (nulleqnull && result == 0)		result = 1;	MemoryContextSwitchTo(oldContext);	return result;}/* * Generate a fake join tuple with nulls for the inner tuple, * and return it if it passes the non-join quals. */static TupleTableSlot *MJFillOuter(MergeJoinState *node){	ExprContext *econtext = node->js.ps.ps_ExprContext;	List	   *otherqual = node->js.ps.qual;	ResetExprContext(econtext);	econtext->ecxt_outertuple = node->mj_OuterTupleSlot;	econtext->ecxt_innertuple = node->mj_NullInnerTupleSlot;	if (ExecQual(otherqual, econtext, false))	{		/*		 * qualification succeeded.  now form the desired projection tuple and		 * return the slot containing it.		 */		TupleTableSlot *result;		ExprDoneCond isDone;		MJ_printf("ExecMergeJoin: returning outer fill tuple\n");		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);		if (isDone != ExprEndResult)		{			node->js.ps.ps_TupFromTlist =				(isDone == ExprMultipleResult);			return result;		}	}	return NULL;}/* * Generate a fake join tuple with nulls for the outer tuple, * and return it if it passes the non-join quals. */static TupleTableSlot *MJFillInner(MergeJoinState *node){	ExprContext *econtext = node->js.ps.ps_ExprContext;	List	   *otherqual = node->js.ps.qual;	ResetExprContext(econtext);	econtext->ecxt_outertuple = node->mj_NullOuterTupleSlot;	econtext->ecxt_innertuple = node->mj_InnerTupleSlot;	if (ExecQual(otherqual, econtext, false))	{		/*		 * qualification succeeded.  now form the desired projection tuple and		 * return the slot containing it.		 */		TupleTableSlot *result;		ExprDoneCond isDone;		MJ_printf("ExecMergeJoin: returning inner fill tuple\n");		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);		if (isDone != ExprEndResult)		{			node->js.ps.ps_TupFromTlist =				(isDone == ExprMultipleResult);			return result;		}	}	return NULL;}/* ---------------------------------------------------------------- *		ExecMergeTupleDump * *		This function is called through the MJ_dump() macro *		when EXEC_MERGEJOINDEBUG is defined * ---------------------------------------------------------------- */#ifdef EXEC_MERGEJOINDEBUGstatic voidExecMergeTupleDumpOuter(MergeJoinState *mergestate){	TupleTableSlot *outerSlot = mergestate->mj_OuterTupleSlot;	printf("==== outer tuple ====\n");	if (TupIsNull(outerSlot))		printf("(nil)\n");	else		MJ_debugtup(outerSlot);}static voidExecMergeTupleDumpInner(MergeJoinState *mergestate){	TupleTableSlot *innerSlot = mergestate->mj_InnerTupleSlot;	printf("==== inner tuple ====\n");	if (TupIsNull(innerSlot))		printf("(nil)\n");	else		MJ_debugtup(innerSlot);}static voidExecMergeTupleDumpMarked(MergeJoinState *mergestate){	TupleTableSlot *markedSlot = mergestate->mj_MarkedTupleSlot;	printf("==== marked tuple ====\n");	if (TupIsNull(markedSlot))		printf("(nil)\n");	else		MJ_debugtup(markedSlot);}static voidExecMergeTupleDump(MergeJoinState *mergestate){	printf("******** ExecMergeTupleDump ********\n");	ExecMergeTupleDumpOuter(mergestate);	ExecMergeTupleDumpInner(mergestate);	ExecMergeTupleDumpMarked(mergestate);	printf("******** \n");}#endif/* ---------------------------------------------------------------- *		ExecMergeJoin * ---------------------------------------------------------------- */TupleTableSlot *ExecMergeJoin(MergeJoinState *node){	EState	   *estate;	List	   *joinqual;	List	   *otherqual;	bool		qualResult;	int			compareResult;	PlanState  *innerPlan;	TupleTableSlot *innerTupleSlot;	PlanState  *outerPlan;	TupleTableSlot *outerTupleSlot;	ExprContext *econtext;	bool		doFillOuter;	bool		doFillInner;	/*	 * get information from node	 */	estate = node->js.ps.state;	innerPlan = innerPlanState(node);	outerPlan = outerPlanState(node);	econtext = node->js.ps.ps_ExprContext;	joinqual = node->js.joinqual;	otherqual = node->js.ps.qual;	doFillOuter = node->mj_FillOuter;	doFillInner = node->mj_FillInner;	/*	 * Check to see if we're still projecting out tuples from a previous join	 * tuple (because there is a function-returning-set in the projection	 * expressions).  If so, try to project another one.	 */	if (node->js.ps.ps_TupFromTlist)	{		TupleTableSlot *result;		ExprDoneCond isDone;		result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);		if (isDone == ExprMultipleResult)			return result;		/* Done with that source tuple... */		node->js.ps.ps_TupFromTlist = false;	}	/*	 * Reset per-tuple memory context to free any expression evaluation	 * storage allocated in the previous tuple cycle.  Note this can't happen	 * until we're done projecting out tuples from a join tuple.	 */	ResetExprContext(econtext);	/*	 * ok, everything is setup.. let's go to work	 */	for (;;)	{		MJ_dump(node);		/*		 * get the current state of the join and do things accordingly.		 */		switch (node->mj_JoinState)		{				/*				 * EXEC_MJ_INITIALIZE_OUTER means that this is the first time				 * ExecMergeJoin() has been called and so we have to fetch the				 * first matchable tuple for both outer and inner subplans. We				 * do the outer side in INITIALIZE_OUTER state, then advance				 * to INITIALIZE_INNER state for the inner subplan.				 */			case EXEC_MJ_INITIALIZE_OUTER:				MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE_OUTER\n");				outerTupleSlot = ExecProcNode(outerPlan);				node->mj_OuterTupleSlot = outerTupleSlot;				if (TupIsNull(outerTupleSlot))				{					MJ_printf("ExecMergeJoin: nothing in outer subplan\n");					if (doFillInner)					{						/*						 * Need to emit right-join tuples for remaining inner						 * tuples.	We set MatchedInner = true to force the						 * ENDOUTER state to advance inner.						 */						node->mj_JoinState = EXEC_MJ_ENDOUTER;						node->mj_MatchedInner = true;						break;					}					/* Otherwise we're done. */					return NULL;				}				/* Compute join values and check for unmatchability */				if (MJEvalOuterValues(node))				{					/* OK to go get the first inner tuple */					node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;				}				else				{					/* Stay in same state to fetch next outer tuple */					if (doFillOuter)					{						/*						 * Generate a fake join tuple with nulls for the inner						 * tuple, and return it if it passes the non-join						 * quals.						 */						TupleTableSlot *result;						result = MJFillOuter(node);						if (result)							return result;					}				}				break;			case EXEC_MJ_INITIALIZE_INNER:				MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE_INNER\n");				innerTupleSlot = ExecProcNode(innerPlan);				node->mj_InnerTupleSlot = innerTupleSlot;				if (TupIsNull(innerTupleSlot))				{					MJ_printf("ExecMergeJoin: nothing in inner subplan\n");					if (doFillOuter)					{						/*						 * Need to emit left-join tuples for all outer tuples,						 * including the one we just fetched.  We set						 * MatchedOuter = false to force the ENDINNER state to						 * emit first tuple before advancing outer.						 */						node->mj_JoinState = EXEC_MJ_ENDINNER;						node->mj_MatchedOuter = false;						break;					}					/* Otherwise we're done. */					return NULL;				}				/* Compute join values and check for unmatchability */				if (MJEvalInnerValues(node, innerTupleSlot))				{					/*					 * OK, we have the initial tuples.	Begin by skipping					 * non-matching tuples.					 */					node->mj_JoinState = EXEC_MJ_SKIP_TEST;				}				else				{					/* Stay in same state to fetch next inner tuple */					if (doFillInner)					{						/*						 * Generate a fake join tuple with nulls for the outer						 * tuple, and return it if it passes the non-join						 * quals.						 */						TupleTableSlot *result;						result = MJFillInner(node);						if (result)							return result;					}				}				break;				/*				 * EXEC_MJ_JOINTUPLES means we have two tuples which satisfied				 * the merge clause so we join them and then proceed to get				 * the next inner tuple (EXEC_MJ_NEXTINNER).				 */			case EXEC_MJ_JOINTUPLES:				MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");				/*

⌨️ 快捷键说明

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