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

📄 nodemergejoin.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
				 * For example:				 *				 *				outer inner				 *				  5		5				 *				  5		5				 * outer tuple - 12		8  - inner tuple				 *				 14    10				 *				 17    12				 *				 * we have to advance the inner scan				 * until we find the inner 12.				 *				 *-------------------------------------------------------				 */			case EXEC_MJ_SKIPINNER:				MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER\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,											 innerSkipQual,											 econtext);				MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);				/* ----------------				 *	compareResult is true as long as we should				 *	continue skipping tuples.				 * ----------------				 */				if (compareResult)				{#ifdef ENABLE_OUTER_JOINS					/* ----------------					 *	if this is a right or full outer join, then fill					 * ----------------					 */					if (isRightJoin)					{						mergestate->mj_JoinState = EXEC_MJ_FILLINNER;						break;					}#endif					/* ----------------					 *	now try and get a new inner tuple					 * ----------------					 */					innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);					MJ_DEBUG_PROC_NODE(innerTupleSlot);					econtext->ecxt_innertuple = innerTupleSlot;					/* ----------------					 *	if the inner tuple is null then we know					 *	we have to restore the inner scan					 *	and advance to the next outer tuple					 * ----------------					 */					if (TupIsNull(innerTupleSlot))					{						/* ----------------						 *	this is an interesting case.. all our						 *	inner tuples are smaller then our outer						 *	tuples so we never found an inner tuple						 *	to mark.						 *						 *			  outer inner						 *	 outer tuple -	5	  4						 *					5	  4						 *					6	 nil  - inner tuple						 *					7						 *						 *	This means the join should end.						 * ----------------						 */						MJ_printf("ExecMergeJoin: **** weird case 2 ****\n");						return NULL;					}					/* ----------------					 *	otherwise test the new tuple against the skip qual.					 *	(we remain in the EXEC_MJ_SKIPINNER state)					 * ----------------					 */					break;				}				/* ----------------				 *	compare finally failed and we have stopped skipping				 *	inner tuples so now check the outer skip qual				 *	to see if we should now skip outer tuples...				 * ----------------				 */				compareResult = MergeCompare(mergeclauses,											 outerSkipQual,											 econtext);				MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);				if (compareResult)					mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER;				else					mergestate->mj_JoinState = EXEC_MJ_JOINMARK;				break;#ifdef ENABLE_OUTER_JOINS				/*				 * EXEC_MJ_FILLINNER means we have an unmatched inner				 * tuple which must be null-expanded into the projection				 * tuple. get the next inner tuple and reset markers				 * (EXEC_MJ_JOINMARK).				 */			case EXEC_MJ_FILLINNER:				MJ_printf("ExecMergeJoin: EXEC_MJ_FILLINNER\n");				mergestate->mj_JoinState = EXEC_MJ_JOINMARK;				/* ----------------				 *	project the inner tuple into the result				 * ----------------				 */				MJ_printf("ExecMergeJoin: project inner tuple into the result (not yet implemented)\n");				/* ----------------				 *	now skip this inner tuple				 * ----------------				 */				innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);				MJ_DEBUG_PROC_NODE(innerTupleSlot);				econtext->ecxt_innertuple = innerTupleSlot;				/* ----------------				 *	if the inner tuple is null then we know				 *	we have to restore the inner scan				 *	and advance to the next outer tuple				 * ----------------				 */				if (TupIsNull(innerTupleSlot))				{					if (isLeftJoin && !TupIsNull(outerTupleSlot))					{						mergestate->mj_JoinState = EXEC_MJ_FILLOUTER;						MJ_printf("ExecMergeJoin: try to complete outer fill\n");						break;					}					MJ_printf("ExecMergeJoin: **** weird case 2 ****\n");					return NULL;				}				/* ----------------				 *	otherwise test the new tuple against the skip qual.				 *	(we move to the EXEC_MJ_JOINMARK state)				 * ----------------				 */				break;				/*				 * EXEC_MJ_FILLOUTER means we have an unmatched outer				 * tuple which must be null-expanded into the projection				 * tuple. get the next outer tuple and reset markers				 * (EXEC_MJ_JOINMARK).				 */			case EXEC_MJ_FILLOUTER:				MJ_printf("ExecMergeJoin: EXEC_MJ_FILLOUTER\n");				mergestate->mj_JoinState = EXEC_MJ_JOINMARK;				/* ----------------				 *	project the outer tuple into the result				 * ----------------				 */				MJ_printf("ExecMergeJoin: project outer tuple into the result (not yet implemented)\n");				/* ----------------				 *	now skip this outer tuple				 * ----------------				 */				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 left half of the join				 * ----------------				 */				if (TupIsNull(outerTupleSlot))				{					if (isRightJoin && !TupIsNull(innerTupleSlot))					{						mergestate->mj_JoinState = EXEC_MJ_FILLINNER;						MJ_printf("ExecMergeJoin: try to complete inner fill\n");						break;					}					MJ_printf("ExecMergeJoin: **** outerTuple is nil ****\n");					return NULL;				}				/* ----------------				 *	otherwise test the new tuple against the skip qual.				 *	(we move to the EXEC_MJ_JOINMARK state)				 * ----------------				 */				break;#endif				/*				 * if we get here it means our code is fouled up and so we				 * just end the join prematurely.				 */			default:				elog(NOTICE, "ExecMergeJoin: invalid join state. aborting");				return NULL;		}	}}/* ---------------------------------------------------------------- *		ExecInitMergeJoin * * old comments *		Creates the run-time state information for the node and *		sets the relation id to contain relevant decriptors. * ---------------------------------------------------------------- */boolExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent){	MergeJoinState *mergestate;	List	   *joinclauses;	TupleTableSlot *mjSlot;	MJ1_printf("ExecInitMergeJoin: %s\n",			   "initializing node");	/* ----------------	 *	assign the node's execution state and	 *	get the range table and direction from it	 * ----------------	 */	node->join.state = estate;	/* ----------------	 *	create new merge state for node	 * ----------------	 */	mergestate = makeNode(MergeJoinState);	mergestate->mj_OuterSkipQual = NIL;	mergestate->mj_InnerSkipQual = NIL;	mergestate->mj_JoinState = 0;	mergestate->mj_MarkedTupleSlot = NULL;	node->mergestate = mergestate;	/* ----------------	 *	Miscellaneous initialization	 *	 *		 +	assign node's base_id	 *		 +	assign debugging hooks and	 *		 +	create expression context for node	 * ----------------	 */	ExecAssignNodeBaseInfo(estate, &mergestate->jstate, parent);	ExecAssignExprContext(estate, &mergestate->jstate);#define MERGEJOIN_NSLOTS 2	/* ----------------	 *	tuple table initialization	 * ----------------	 */	ExecInitResultTupleSlot(estate, &mergestate->jstate);	mjSlot = (TupleTableSlot *) palloc(sizeof(TupleTableSlot));	mjSlot->val = NULL;	mjSlot->ttc_shouldFree = true;	mjSlot->ttc_tupleDescriptor = NULL;	mjSlot->ttc_whichplan = -1;	mjSlot->ttc_descIsNew = true;	mergestate->mj_MarkedTupleSlot = mjSlot;	/* ----------------	 *	form merge skip qualifications	 * ----------------	 */	joinclauses = node->mergeclauses;	mergestate->mj_OuterSkipQual = MJFormSkipQual(joinclauses, "<");	mergestate->mj_InnerSkipQual = MJFormSkipQual(joinclauses, ">");	MJ_printf("\nExecInitMergeJoin: OuterSkipQual is ");	MJ_nodeDisplay(mergestate->mj_OuterSkipQual);	MJ_printf("\nExecInitMergeJoin: InnerSkipQual is ");	MJ_nodeDisplay(mergestate->mj_InnerSkipQual);	MJ_printf("\n");	/* ----------------	 *	initialize join state	 * ----------------	 */	mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;	/* ----------------	 *	initialize subplans	 * ----------------	 */	ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);	ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);	/* ----------------	 *	initialize tuple type and projection info	 * ----------------	 */	ExecAssignResultTypeFromTL((Plan *) node, &mergestate->jstate);	ExecAssignProjectionInfo((Plan *) node, &mergestate->jstate);	mergestate->jstate.cs_TupFromTlist = false;	/* ----------------	 *	initialization successful	 * ----------------	 */	MJ1_printf("ExecInitMergeJoin: %s\n",			   "node initialized");	return TRUE;}intExecCountSlotsMergeJoin(MergeJoin *node){	return ExecCountSlotsNode(outerPlan((Plan *) node)) +	ExecCountSlotsNode(innerPlan((Plan *) node)) +	MERGEJOIN_NSLOTS;}/* ---------------------------------------------------------------- *		ExecEndMergeJoin * * old comments *		frees storage allocated through C routines. * ---------------------------------------------------------------- */voidExecEndMergeJoin(MergeJoin *node){	MergeJoinState *mergestate;	MJ1_printf("ExecEndMergeJoin: %s\n",			   "ending node processing");	/* ----------------	 *	get state information from the node	 * ----------------	 */	mergestate = node->mergestate;	/* ----------------	 *	Free the projection info and the scan attribute info	 *	 *	Note: we don't ExecFreeResultType(mergestate)	 *		  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(&mergestate->jstate);	/* ----------------	 *	shut down the subplans	 * ----------------	 */	ExecEndNode((Plan *) innerPlan((Plan *) node), (Plan *) node);	ExecEndNode((Plan *) outerPlan((Plan *) node), (Plan *) node);	/* ----------------	 *	clean out the tuple table so that we don't try and	 *	pfree the marked tuples..  see HACK ALERT at the top of	 *	this file.	 * ----------------	 */	ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);	ExecClearTuple(mergestate->mj_MarkedTupleSlot);	pfree(mergestate->mj_MarkedTupleSlot);	mergestate->mj_MarkedTupleSlot = NULL;	MJ1_printf("ExecEndMergeJoin: %s\n",			   "node processing ended");}voidExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent){	MergeJoinState *mergestate = node->mergestate;	TupleTableSlot *mjSlot = mergestate->mj_MarkedTupleSlot;	ExecClearTuple(mjSlot);	mjSlot->val = NULL;	mjSlot->ttc_shouldFree = true;	mjSlot->ttc_tupleDescriptor = NULL;	mjSlot->ttc_whichplan = -1;	mjSlot->ttc_descIsNew = true;	mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;	/*	 * if chgParam of subnodes is not null then plans will be re-scanned	 * by first ExecProcNode.	 */	if (((Plan *) node)->lefttree->chgParam == NULL)		ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);	if (((Plan *) node)->righttree->chgParam == NULL)		ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);}

⌨️ 快捷键说明

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