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

📄 nodesubplan.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
				rowresult = expresult;				rownull = expnull;			}			else if (useOr)			{				/* combine within row per OR semantics */				if (expnull)					rownull = true;				else if (DatumGetBool(expresult))				{					rowresult = BoolGetDatum(true);					rownull = false;					break;		/* needn't look at any more columns */				}			}			else			{				/* combine within row per AND semantics */				if (expnull)					rownull = true;				else if (!DatumGetBool(expresult))				{					rowresult = BoolGetDatum(false);					rownull = false;					break;		/* needn't look at any more columns */				}			}			col++;		}		if (subLinkType == ANY_SUBLINK)		{			/* combine across rows per OR semantics */			if (rownull)				*isNull = true;			else if (DatumGetBool(rowresult))			{				result = BoolGetDatum(true);				*isNull = false;				break;			/* needn't look at any more rows */			}		}		else if (subLinkType == ALL_SUBLINK)		{			/* combine across rows per AND semantics */			if (rownull)				*isNull = true;			else if (!DatumGetBool(rowresult))			{				result = BoolGetDatum(false);				*isNull = false;				break;			/* needn't look at any more rows */			}		}		else		{			/* must be MULTIEXPR_SUBLINK */			result = rowresult;			*isNull = rownull;		}	}	if (!found)	{		/*		 * deal with empty subplan result.	result/isNull were previously		 * initialized correctly for all sublink types except EXPR, ARRAY, and		 * MULTIEXPR; for those, return NULL.		 */		if (subLinkType == EXPR_SUBLINK ||			subLinkType == ARRAY_SUBLINK ||			subLinkType == MULTIEXPR_SUBLINK)		{			result = (Datum) 0;			*isNull = true;		}	}	else if (subLinkType == ARRAY_SUBLINK)	{		Assert(astate != NULL);		/* We return the result in the caller's context */		result = makeArrayResult(astate, oldcontext);	}	MemoryContextSwitchTo(oldcontext);	return result;}/* * buildSubPlanHash: load hash table by scanning subplan output. */static voidbuildSubPlanHash(SubPlanState *node){	SubPlan    *subplan = (SubPlan *) node->xprstate.expr;	PlanState  *planstate = node->planstate;	int			ncols = list_length(node->exprs);	ExprContext *innerecontext = node->innerecontext;	MemoryContext tempcxt = innerecontext->ecxt_per_tuple_memory;	MemoryContext oldcontext;	int			nbuckets;	TupleTableSlot *slot;	Assert(subplan->subLinkType == ANY_SUBLINK);	Assert(!subplan->useOr);	/*	 * If we already had any hash tables, destroy 'em; then create empty hash	 * table(s).	 *	 * If we need to distinguish accurately between FALSE and UNKNOWN (i.e.,	 * NULL) results of the IN operation, then we have to store subplan output	 * rows that are partly or wholly NULL.  We store such rows in a separate	 * hash table that we expect will be much smaller than the main table. (We	 * can use hashing to eliminate partly-null rows that are not distinct.	 * We keep them separate to minimize the cost of the inevitable full-table	 * searches; see findPartialMatch.)	 *	 * If it's not necessary to distinguish FALSE and UNKNOWN, then we don't	 * need to store subplan output rows that contain NULL.	 */	MemoryContextReset(node->tablecxt);	node->hashtable = NULL;	node->hashnulls = NULL;	node->havehashrows = false;	node->havenullrows = false;	nbuckets = (int) ceil(planstate->plan->plan_rows);	if (nbuckets < 1)		nbuckets = 1;	node->hashtable = BuildTupleHashTable(ncols,										  node->keyColIdx,										  node->eqfunctions,										  node->hashfunctions,										  nbuckets,										  sizeof(TupleHashEntryData),										  node->tablecxt,										  tempcxt);	if (!subplan->unknownEqFalse)	{		if (ncols == 1)			nbuckets = 1;		/* there can only be one entry */		else		{			nbuckets /= 16;			if (nbuckets < 1)				nbuckets = 1;		}		node->hashnulls = BuildTupleHashTable(ncols,											  node->keyColIdx,											  node->eqfunctions,											  node->hashfunctions,											  nbuckets,											  sizeof(TupleHashEntryData),											  node->tablecxt,											  tempcxt);	}	/*	 * We are probably in a short-lived expression-evaluation context. Switch	 * to the child plan's per-query context for calling ExecProcNode.	 */	oldcontext = MemoryContextSwitchTo(node->sub_estate->es_query_cxt);	/*	 * Reset subplan to start.	 */	ExecReScan(planstate, NULL);	/*	 * Scan the subplan and load the hash table(s).  Note that when there are	 * duplicate rows coming out of the sub-select, only one copy is stored.	 */	for (slot = ExecProcNode(planstate);		 !TupIsNull(slot);		 slot = ExecProcNode(planstate))	{		int			col = 1;		ListCell   *plst;		bool		isnew;		/*		 * Load up the Params representing the raw sub-select outputs, then		 * form the projection tuple to store in the hashtable.		 */		foreach(plst, subplan->paramIds)		{			int			paramid = lfirst_int(plst);			ParamExecData *prmdata;			prmdata = &(innerecontext->ecxt_param_exec_vals[paramid]);			Assert(prmdata->execPlan == NULL);			prmdata->value = slot_getattr(slot, col,										  &(prmdata->isnull));			col++;		}		slot = ExecProject(node->projRight, NULL);		/*		 * If result contains any nulls, store separately or not at all.		 */		if (slotNoNulls(slot))		{			(void) LookupTupleHashEntry(node->hashtable, slot, &isnew);			node->havehashrows = true;		}		else if (node->hashnulls)		{			(void) LookupTupleHashEntry(node->hashnulls, slot, &isnew);			node->havenullrows = true;		}		/*		 * Reset innerecontext after each inner tuple to free any memory used		 * in hash computation or comparison routines.		 */		ResetExprContext(innerecontext);	}	/*	 * Since the projected tuples are in the sub-query's context and not the	 * main context, we'd better clear the tuple slot before there's any	 * chance of a reset of the sub-query's context.  Else we will have the	 * potential for a double free attempt.  (XXX possibly no longer needed,	 * but can't hurt.)	 */	ExecClearTuple(node->projRight->pi_slot);	MemoryContextSwitchTo(oldcontext);}/* * findPartialMatch: does the hashtable contain an entry that is not * provably distinct from the tuple? * * We have to scan the whole hashtable; we can't usefully use hashkeys * to guide probing, since we might get partial matches on tuples with * hashkeys quite unrelated to what we'd get from the given tuple. */static boolfindPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot){	int			numCols = hashtable->numCols;	AttrNumber *keyColIdx = hashtable->keyColIdx;	TupleHashIterator hashiter;	TupleHashEntry entry;	ResetTupleHashIterator(hashtable, &hashiter);	while ((entry = ScanTupleHashTable(&hashiter)) != NULL)	{		ExecStoreTuple(entry->firstTuple, hashtable->tableslot,					   InvalidBuffer, false);		if (!execTuplesUnequal(hashtable->tableslot, slot,							   numCols, keyColIdx,							   hashtable->eqfunctions,							   hashtable->tempcxt))			return true;	}	return false;}/* * slotAllNulls: is the slot completely NULL? * * This does not test for dropped columns, which is OK because we only * use it on projected tuples. */static boolslotAllNulls(TupleTableSlot *slot){	int			ncols = slot->tts_tupleDescriptor->natts;	int			i;	for (i = 1; i <= ncols; i++)	{		if (!slot_attisnull(slot, i))			return false;	}	return true;}/* * slotNoNulls: is the slot entirely not NULL? * * This does not test for dropped columns, which is OK because we only * use it on projected tuples. */static boolslotNoNulls(TupleTableSlot *slot){	int			ncols = slot->tts_tupleDescriptor->natts;	int			i;	for (i = 1; i <= ncols; i++)	{		if (slot_attisnull(slot, i))			return false;	}	return true;}/* ---------------------------------------------------------------- *		ExecInitSubPlan * ---------------------------------------------------------------- */voidExecInitSubPlan(SubPlanState *node, EState *estate){	SubPlan    *subplan = (SubPlan *) node->xprstate.expr;	EState	   *sp_estate;	MemoryContext oldcontext;	/*	 * Do access checking on the rangetable entries in the subquery.	 */	ExecCheckRTPerms(subplan->rtable);	/*	 * initialize my state	 */	node->needShutdown = false;	node->curTuple = NULL;	node->projLeft = NULL;	node->projRight = NULL;	node->hashtable = NULL;	node->hashnulls = NULL;	node->tablecxt = NULL;	node->innerecontext = NULL;	node->keyColIdx = NULL;	node->eqfunctions = NULL;	node->hashfunctions = NULL;	/*	 * create an EState for the subplan	 *	 * The subquery needs its own EState because it has its own rangetable. It	 * shares our Param ID space, however.	XXX if rangetable access were done	 * differently, the subquery could share our EState, which would eliminate	 * some thrashing about in this module...	 */	sp_estate = CreateExecutorState();	node->sub_estate = sp_estate;	oldcontext = MemoryContextSwitchTo(sp_estate->es_query_cxt);	sp_estate->es_range_table = subplan->rtable;	sp_estate->es_param_list_info = estate->es_param_list_info;	sp_estate->es_param_exec_vals = estate->es_param_exec_vals;	sp_estate->es_tupleTable =		ExecCreateTupleTable(ExecCountSlotsNode(subplan->plan) + 10);	sp_estate->es_snapshot = estate->es_snapshot;	sp_estate->es_crosscheck_snapshot = estate->es_crosscheck_snapshot;	sp_estate->es_instrument = estate->es_instrument;	/*	 * Start up the subplan (this is a very cut-down form of InitPlan())	 */	node->planstate = ExecInitNode(subplan->plan, sp_estate);	node->needShutdown = true;	/* now we need to shutdown the subplan */	MemoryContextSwitchTo(oldcontext);

⌨️ 快捷键说明

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