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

📄 nodemergejoin.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
	outerPlan = outerPlan((Plan *) node);	econtext = mergestate->jstate.cs_ExprContext;	mergeclauses = node->mergeclauses;	qual = node->join.qual;	if (ScanDirectionIsForward(direction))	{		outerSkipQual = mergestate->mj_OuterSkipQual;		innerSkipQual = mergestate->mj_InnerSkipQual;	}	else	{		outerSkipQual = mergestate->mj_InnerSkipQual;		innerSkipQual = mergestate->mj_OuterSkipQual;	}	/* ----------------	 *	ok, everything is setup.. let's go to work	 * ----------------	 */	if (mergestate->jstate.cs_TupFromTlist)	{		TupleTableSlot *result;		ProjectionInfo *projInfo;		bool		isDone;		projInfo = mergestate->jstate.cs_ProjInfo;		result = ExecProject(projInfo, &isDone);		if (!isDone)			return result;	}	for (;;)	{		/* ----------------		 *	get the current state of the join and do things accordingly.		 *	Note: The join states are highlighted with 32-* comments for		 *		  improved readability.		 * ----------------		 */		MJ_dump(econtext, mergestate);		switch (mergestate->mj_JoinState)		{				/*				 * EXEC_MJ_INITIALIZE means that this is the first time				 * ExecMergeJoin() has been called and so we have to				 * initialize the inner, outer and marked tuples as well				 * as various stuff in the expression context.				 */			case EXEC_MJ_INITIALIZE:				MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");				/*				 * Note: at this point, if either of our inner or outer				 * tuples are nil, then the join ends immediately because				 * we know one of the subplans is empty.				 */				innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);				if (TupIsNull(innerTupleSlot))				{					MJ_printf("ExecMergeJoin: **** inner tuple is nil ****\n");					return NULL;				}				outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);				if (TupIsNull(outerTupleSlot))				{					MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");					return NULL;				}				/* ----------------				 *	 store the inner and outer tuple in the merge state				 * ----------------				 */				econtext->ecxt_innertuple = innerTupleSlot;				econtext->ecxt_outertuple = outerTupleSlot;				mergestate->mj_MarkedTupleSlot->ttc_tupleDescriptor =					innerTupleSlot->ttc_tupleDescriptor;				/* ----------------				 *	initialize merge join state to skip inner tuples.				 * ----------------				 */				mergestate->mj_JoinState = EXEC_MJ_SKIPINNER;				break;				/*				 * EXEC_MJ_JOINMARK means we have just found a new outer				 * tuple and a possible matching inner tuple. This is the				 * case after the INITIALIZE, SKIPOUTER or SKIPINNER				 * states.				 */			case EXEC_MJ_JOINMARK:				MJ_printf("ExecMergeJoin: EXEC_MJ_JOINMARK\n");				ExecMarkPos(innerPlan);				MarkInnerTuple(econtext->ecxt_innertuple, mergestate);				mergestate->mj_JoinState = EXEC_MJ_JOINTEST;				break;				/*				 * EXEC_MJ_JOINTEST means we have two tuples which might				 * satisfy the merge clause, so we test them.				 *				 * If they do satisfy, then we join them and move on to the				 * next inner tuple (EXEC_MJ_JOINTUPLES).				 *				 * If they do not satisfy then advance to next outer tuple.				 */			case EXEC_MJ_JOINTEST:				MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTEST\n");				qualResult = ExecQual((List *) mergeclauses, econtext);				MJ_DEBUG_QUAL(mergeclauses, qualResult);				if (qualResult)					mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;				else					mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;				break;				/*				 * EXEC_MJ_JOINTUPLES means we have two tuples which				 * satisified the merge clause so we join them and then				 * proceed to get the next inner tuple (EXEC_NEXT_INNER).				 */			case EXEC_MJ_JOINTUPLES:				MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");				mergestate->mj_JoinState = EXEC_MJ_NEXTINNER;				qualResult = ExecQual((List *) qual, econtext);				MJ_DEBUG_QUAL(qual, qualResult);				if (qualResult)				{					/* ----------------					 *	qualification succeeded.  now form the desired					 *	projection tuple and return the slot containing it.					 * ----------------					 */					ProjectionInfo *projInfo;					TupleTableSlot *result;					bool		isDone;					MJ_printf("ExecMergeJoin: **** returning tuple ****\n");					projInfo = mergestate->jstate.cs_ProjInfo;					result = ExecProject(projInfo, &isDone);					mergestate->jstate.cs_TupFromTlist = !isDone;					return result;				}				break;				/*				 * EXEC_MJ_NEXTINNER means advance the inner scan to the				 * next tuple. If the tuple is not nil, we then proceed to				 * test it against the join qualification.				 */			case EXEC_MJ_NEXTINNER:				MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");				/* ----------------				 *	now we get the next inner tuple, if any				 * ----------------				 */				innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);				MJ_DEBUG_PROC_NODE(innerTupleSlot);				econtext->ecxt_innertuple = innerTupleSlot;				if (TupIsNull(innerTupleSlot))					mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;				else					mergestate->mj_JoinState = EXEC_MJ_JOINTEST;				break;				/*-------------------------------------------				 * EXEC_MJ_NEXTOUTER means				 *				 *				outer inner				 * outer tuple -  5		5  - marked tuple				 *				  5		5				 *				  6		6  - inner tuple				 *				  7		7				 *				 * we know we just bumped into the				 * first inner tuple > current outer tuple				 * so get a new outer tuple and then				 * proceed to test it against the marked tuple				 * (EXEC_MJ_TESTOUTER)				 *------------------------------------------------				 */			case EXEC_MJ_NEXTOUTER:				MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");				outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);				MJ_DEBUG_PROC_NODE(outerTupleSlot);				econtext->ecxt_outertuple = outerTupleSlot;				/* ----------------				 *	if the outer tuple is null then we know				 *	we are done with the join				 * ----------------				 */				if (TupIsNull(outerTupleSlot))				{					MJ_printf("ExecMergeJoin: **** outer tuple is nil ****\n");					return NULL;				}				mergestate->mj_JoinState = EXEC_MJ_TESTOUTER;				break;				/*--------------------------------------------------------				 * EXEC_MJ_TESTOUTER If the new outer tuple and the marked				 * tuple satisfy the merge clause then we know we have				 * duplicates in the outer scan so we have to restore the				 * inner scan to the marked tuple and proceed to join the				 * new outer tuples with the inner tuples (EXEC_MJ_JOINTEST)				 *				 * This is the case when				 *						  outer inner				 *							4	  5  - marked tuple				 *			 outer tuple -	5	  5				 *		 new outer tuple -	5	  5				 *							6	  8  - inner tuple				 *							7	 12				 *				 *				new outer tuple = marked tuple				 *				 *		If the outer tuple fails the test, then we know we have				 *		to proceed to skip outer tuples until outer >= inner				 *		(EXEC_MJ_SKIPOUTER).				 *				 *		This is the case when				 *				 *						  outer inner				 *							5	  5  - marked tuple				 *			 outer tuple -	5	  5				 *		 new outer tuple -	6	  8  - inner tuple				 *							7	 12				 *				 *				 *		 new outer tuple > marked tuple				 *				 *---------------------------------------------------------				 */			case EXEC_MJ_TESTOUTER:				MJ_printf("ExecMergeJoin: EXEC_MJ_TESTOUTER\n");				/* ----------------				 *	here we compare the outer tuple with the marked inner tuple				 *	by using the marked tuple in place of the inner tuple.				 * ----------------				 */				innerTupleSlot = econtext->ecxt_innertuple;				econtext->ecxt_innertuple = mergestate->mj_MarkedTupleSlot;				qualResult = ExecQual((List *) mergeclauses, econtext);				MJ_DEBUG_QUAL(mergeclauses, qualResult);				if (qualResult)				{					/*					 * the merge clause matched so now we juggle the slots					 * back the way they were and proceed to JOINTEST.					 *					 * I can't understand why we have to go to JOINTEST and					 * compare outer tuple with the same inner one again					 * -> go to JOINTUPLES...	 - vadim 02/27/98					 */					ExecRestrPos(innerPlan);#if 0					mergestate->mj_JoinState = EXEC_MJ_JOINTEST;#endif					mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;				}				else				{					econtext->ecxt_innertuple = innerTupleSlot;					/* ----------------					 *	if the inner tuple was nil and the new outer					 *	tuple didn't match the marked outer tuple then					 *	we may have the case:					 *					 *			 outer inner					 *			   4	 4	- marked tuple					 * new outer - 5	 4					 *			   6	nil - inner tuple					 *			   7					 *					 *	which means that all subsequent outer tuples will be					 *	larger than our inner tuples.					 * ----------------					 */					if (TupIsNull(innerTupleSlot))					{#ifdef ENABLE_OUTER_JOINS						if (isLeftJoin)						{							/* continue on to null fill outer tuples */							mergestate->mj_JoinState = EXEC_MJ_FILLOUTER;							break;						}#endif						MJ_printf("ExecMergeJoin: **** weird case 1 ****\n");						return NULL;					}					/* continue on to skip outer tuples */					mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;				}				break;				/*----------------------------------------------------------				 * EXEC_MJ_SKIPOUTER means skip over tuples in the outer plan				 * until we find an outer tuple > current inner tuple.				 *				 * For example:				 *				 *				outer inner				 *				  5		5				 *				  5		5				 * outer tuple -  6		8  - inner tuple				 *				  7    12				 *				  8    14				 *				 * we have to advance the outer scan				 * until we find the outer 8.				 *----------------------------------------------------------				 */			case EXEC_MJ_SKIPOUTER:				MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER\n");				/* ----------------				 *	before we advance, make sure the current tuples				 *	do not satisfy the mergeclauses.  If they do, then				 *	we update the marked tuple and go join them.				 * ----------------				 */				qualResult = ExecQual((List *) mergeclauses, econtext);				MJ_DEBUG_QUAL(mergeclauses, qualResult);				if (qualResult)				{					ExecMarkPos(innerPlan);					MarkInnerTuple(econtext->ecxt_innertuple, mergestate);					mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;					break;				}				/* ----------------				 *	ok, now test the skip qualification				 * ----------------				 */				compareResult = MergeCompare(mergeclauses,											 outerSkipQual,											 econtext);				MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);				/* ----------------				 *	compareResult is true as long as we should				 *	continue skipping tuples.				 * ----------------				 */				if (compareResult)				{#ifdef ENABLE_OUTER_JOINS					/* ----------------					 *	if this is a left or full outer join, then fill					 * ----------------					 */					if (isLeftJoin)					{						mergestate->mj_JoinState = EXEC_MJ_FILLOUTER;						break;					}#endif					outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);					MJ_DEBUG_PROC_NODE(outerTupleSlot);					econtext->ecxt_outertuple = outerTupleSlot;					/* ----------------					 *	if the outer tuple is null then we know					 *	we are done with the join					 * ----------------					 */					if (TupIsNull(outerTupleSlot))					{						MJ_printf("ExecMergeJoin: **** outerTuple is nil ****\n");						return NULL;					}					/* ----------------					 *	otherwise test the new tuple against the skip qual.					 *	(we remain in the EXEC_MJ_SKIPOUTER state)					 * ----------------					 */					break;				}				/* ----------------				 *	now check the inner skip qual to see if we				 *	should now skip inner tuples... if we fail the				 *	inner skip qual, then we know we have a new pair				 *	of matching tuples.				 * ----------------				 */				compareResult = MergeCompare(mergeclauses,											 innerSkipQual,											 econtext);				MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);				if (compareResult)					mergestate->mj_JoinState = EXEC_MJ_SKIPINNER;				else					mergestate->mj_JoinState = EXEC_MJ_JOINMARK;				break;				/*-----------------------------------------------------------				 * EXEC_MJ_SKIPINNER means skip over tuples in the inner plan				 * until we find an inner tuple > current outer tuple.				 *

⌨️ 快捷键说明

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