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

📄 nodemergejoin.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
						return result;				}				/*				 * now we get the next outer tuple, if any				 */				outerTupleSlot = ExecProcNode(outerPlan);				node->mj_OuterTupleSlot = outerTupleSlot;				MJ_DEBUG_PROC_NODE(outerTupleSlot);				node->mj_MatchedOuter = false;				/*				 * if the outer tuple is null then we are done with the join,				 * unless we have inner tuples we need to null-fill.				 */				if (TupIsNull(outerTupleSlot))				{					MJ_printf("ExecMergeJoin: end of outer subplan\n");					innerTupleSlot = node->mj_InnerTupleSlot;					if (doFillInner && !TupIsNull(innerTupleSlot))					{						/*						 * Need to emit right-join tuples for remaining inner						 * tuples.						 */						node->mj_JoinState = EXEC_MJ_ENDOUTER;						break;					}					/* Otherwise we're done. */					return NULL;				}				/* Compute join values and check for unmatchability */				if (MJEvalOuterValues(node))				{					/* Go test the new tuple against the current inner */					node->mj_JoinState = EXEC_MJ_SKIP_TEST;				}				else				{					/* Can't match, so fetch next outer tuple */					node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;				}				break;				/*				 * Before advancing, we check to see if we must emit an				 * outer-join fill tuple for this inner tuple.				 */			case EXEC_MJ_SKIPINNER_ADVANCE:				MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");				if (doFillInner && !node->mj_MatchedInner)				{					/*					 * Generate a fake join tuple with nulls for the outer					 * tuple, and return it if it passes the non-join quals.					 */					TupleTableSlot *result;					node->mj_MatchedInner = true;		/* do it only once */					result = MJFillInner(node);					if (result)						return result;				}				/*				 * now we get the next inner tuple, if any				 */				innerTupleSlot = ExecProcNode(innerPlan);				node->mj_InnerTupleSlot = innerTupleSlot;				MJ_DEBUG_PROC_NODE(innerTupleSlot);				node->mj_MatchedInner = false;				/*				 * if the inner tuple is null then we are done with the join,				 * unless we have outer tuples we need to null-fill.				 */				if (TupIsNull(innerTupleSlot))				{					MJ_printf("ExecMergeJoin: end of inner subplan\n");					outerTupleSlot = node->mj_OuterTupleSlot;					if (doFillOuter && !TupIsNull(outerTupleSlot))					{						/*						 * Need to emit left-join tuples for remaining outer						 * tuples.						 */						node->mj_JoinState = EXEC_MJ_ENDINNER;						break;					}					/* Otherwise we're done. */					return NULL;				}				/* Compute join values and check for unmatchability */				if (MJEvalInnerValues(node, innerTupleSlot))				{					/* proceed to compare it to the current outer */					node->mj_JoinState = EXEC_MJ_SKIP_TEST;				}				else				{					/*					 * current inner can't possibly match any outer;					 * better to advance the inner scan than the outer.					 */					node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;				}				break;				/*				 * EXEC_MJ_ENDOUTER means we have run out of outer tuples, but				 * are doing a right/full join and therefore must null-fill				 * any remaing unmatched inner tuples.				 */			case EXEC_MJ_ENDOUTER:				MJ_printf("ExecMergeJoin: EXEC_MJ_ENDOUTER\n");				Assert(doFillInner);				if (!node->mj_MatchedInner)				{					/*					 * Generate a fake join tuple with nulls for the outer					 * tuple, and return it if it passes the non-join quals.					 */					TupleTableSlot *result;					node->mj_MatchedInner = true;		/* do it only once */					result = MJFillInner(node);					if (result)						return result;				}				/*				 * now we get the next inner tuple, if any				 */				innerTupleSlot = ExecProcNode(innerPlan);				node->mj_InnerTupleSlot = innerTupleSlot;				MJ_DEBUG_PROC_NODE(innerTupleSlot);				node->mj_MatchedInner = false;				if (TupIsNull(innerTupleSlot))				{					MJ_printf("ExecMergeJoin: end of inner subplan\n");					return NULL;				}				/* Else remain in ENDOUTER state and process next tuple. */				break;				/*				 * EXEC_MJ_ENDINNER means we have run out of inner tuples, but				 * are doing a left/full join and therefore must null- fill				 * any remaing unmatched outer tuples.				 */			case EXEC_MJ_ENDINNER:				MJ_printf("ExecMergeJoin: EXEC_MJ_ENDINNER\n");				Assert(doFillOuter);				if (!node->mj_MatchedOuter)				{					/*					 * Generate a fake join tuple with nulls for the inner					 * tuple, and return it if it passes the non-join quals.					 */					TupleTableSlot *result;					node->mj_MatchedOuter = true;		/* do it only once */					result = MJFillOuter(node);					if (result)						return result;				}				/*				 * now we get the next outer tuple, if any				 */				outerTupleSlot = ExecProcNode(outerPlan);				node->mj_OuterTupleSlot = outerTupleSlot;				MJ_DEBUG_PROC_NODE(outerTupleSlot);				node->mj_MatchedOuter = false;				if (TupIsNull(outerTupleSlot))				{					MJ_printf("ExecMergeJoin: end of outer subplan\n");					return NULL;				}				/* Else remain in ENDINNER state and process next tuple. */				break;				/*				 * broken state value?				 */			default:				elog(ERROR, "unrecognized mergejoin state: %d",					 (int) node->mj_JoinState);		}	}}/* ---------------------------------------------------------------- *		ExecInitMergeJoin * ---------------------------------------------------------------- */MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate){	MergeJoinState *mergestate;	MJ1_printf("ExecInitMergeJoin: %s\n",			   "initializing node");	/*	 * create state structure	 */	mergestate = makeNode(MergeJoinState);	mergestate->js.ps.plan = (Plan *) node;	mergestate->js.ps.state = estate;	/*	 * Miscellaneous initialization	 *	 * create expression context for node	 */	ExecAssignExprContext(estate, &mergestate->js.ps);	/*	 * we need two additional econtexts in which we can compute the join	 * expressions from the left and right input tuples.  The node's regular	 * econtext won't do because it gets reset too often.	 */	mergestate->mj_OuterEContext = CreateExprContext(estate);	mergestate->mj_InnerEContext = CreateExprContext(estate);	/*	 * initialize child expressions	 */	mergestate->js.ps.targetlist = (List *)		ExecInitExpr((Expr *) node->join.plan.targetlist,					 (PlanState *) mergestate);	mergestate->js.ps.qual = (List *)		ExecInitExpr((Expr *) node->join.plan.qual,					 (PlanState *) mergestate);	mergestate->js.jointype = node->join.jointype;	mergestate->js.joinqual = (List *)		ExecInitExpr((Expr *) node->join.joinqual,					 (PlanState *) mergestate);	/* mergeclauses are handled below */	/*	 * initialize child nodes	 */	outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate);	innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate);#define MERGEJOIN_NSLOTS 4	/*	 * tuple table initialization	 */	ExecInitResultTupleSlot(estate, &mergestate->js.ps);	mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);	ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,						  ExecGetResultType(innerPlanState(mergestate)),						  false);	switch (node->join.jointype)	{		case JOIN_INNER:		case JOIN_IN:			mergestate->mj_FillOuter = false;			mergestate->mj_FillInner = false;			break;		case JOIN_LEFT:			mergestate->mj_FillOuter = true;			mergestate->mj_FillInner = false;			mergestate->mj_NullInnerTupleSlot =				ExecInitNullTupleSlot(estate,							  ExecGetResultType(innerPlanState(mergestate)));			break;		case JOIN_RIGHT:			mergestate->mj_FillOuter = false;			mergestate->mj_FillInner = true;			mergestate->mj_NullOuterTupleSlot =				ExecInitNullTupleSlot(estate,							  ExecGetResultType(outerPlanState(mergestate)));			/*			 * Can't handle right or full join with non-nil extra joinclauses.			 * This should have been caught by planner.			 */			if (node->join.joinqual != NIL)				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));			break;		case JOIN_FULL:			mergestate->mj_FillOuter = true;			mergestate->mj_FillInner = true;			mergestate->mj_NullOuterTupleSlot =				ExecInitNullTupleSlot(estate,							  ExecGetResultType(outerPlanState(mergestate)));			mergestate->mj_NullInnerTupleSlot =				ExecInitNullTupleSlot(estate,							  ExecGetResultType(innerPlanState(mergestate)));			/*			 * Can't handle right or full join with non-nil extra joinclauses.			 */			if (node->join.joinqual != NIL)				ereport(ERROR,						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),						 errmsg("FULL JOIN is only supported with merge-joinable join conditions")));			break;		default:			elog(ERROR, "unrecognized join type: %d",				 (int) node->join.jointype);	}	/*	 * initialize tuple type and projection info	 */	ExecAssignResultTypeFromTL(&mergestate->js.ps);	ExecAssignProjectionInfo(&mergestate->js.ps);	/*	 * preprocess the merge clauses	 */	mergestate->mj_NumClauses = list_length(node->mergeclauses);	mergestate->mj_Clauses = MJExamineQuals(node->mergeclauses,											(PlanState *) mergestate);	/*	 * initialize join state	 */	mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;	mergestate->js.ps.ps_TupFromTlist = false;	mergestate->mj_MatchedOuter = false;	mergestate->mj_MatchedInner = false;	mergestate->mj_OuterTupleSlot = NULL;	mergestate->mj_InnerTupleSlot = NULL;	/*	 * initialization successful	 */	MJ1_printf("ExecInitMergeJoin: %s\n",			   "node initialized");	return mergestate;}intExecCountSlotsMergeJoin(MergeJoin *node){	return ExecCountSlotsNode(outerPlan((Plan *) node)) +		ExecCountSlotsNode(innerPlan((Plan *) node)) +		MERGEJOIN_NSLOTS;}/* ---------------------------------------------------------------- *		ExecEndMergeJoin * * old comments *		frees storage allocated through C routines. * ---------------------------------------------------------------- */voidExecEndMergeJoin(MergeJoinState *node){	MJ1_printf("ExecEndMergeJoin: %s\n",			   "ending node processing");	/*	 * Free the exprcontext	 */	ExecFreeExprContext(&node->js.ps);	/*	 * clean out the tuple table	 */	ExecClearTuple(node->js.ps.ps_ResultTupleSlot);	ExecClearTuple(node->mj_MarkedTupleSlot);	/*	 * shut down the subplans	 */	ExecEndNode(innerPlanState(node));	ExecEndNode(outerPlanState(node));	MJ1_printf("ExecEndMergeJoin: %s\n",			   "node processing ended");}voidExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt){	ExecClearTuple(node->mj_MarkedTupleSlot);	node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;	node->js.ps.ps_TupFromTlist = false;	node->mj_MatchedOuter = false;	node->mj_MatchedInner = false;	node->mj_OuterTupleSlot = NULL;	node->mj_InnerTupleSlot = NULL;	/*	 * if chgParam of subnodes is not null then plans will be re-scanned by	 * first ExecProcNode.	 */	if (((PlanState *) node)->lefttree->chgParam == NULL)		ExecReScan(((PlanState *) node)->lefttree, exprCtxt);	if (((PlanState *) node)->righttree->chgParam == NULL)		ExecReScan(((PlanState *) node)->righttree, exprCtxt);}

⌨️ 快捷键说明

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