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

📄 execmain.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 4 页
字号:
			Datum		datum;			HeapTuple	newTuple;			bool		isNull;			/*			 * extract the 'ctid' junk attribute.			 */			if (operation == CMD_UPDATE || operation == CMD_DELETE)			{				if (!ExecGetJunkAttribute(junkfilter,										  slot,										  "ctid",										  &datum,										  &isNull))					elog(ERROR, "ExecutePlan: NO (junk) `ctid' was found!");				if (isNull)					elog(ERROR, "ExecutePlan: (junk) `ctid' is NULL!");				tupleid = (ItemPointer) DatumGetPointer(datum);				tuple_ctid = *tupleid;	/* make sure we don't free the										 * ctid!! */				tupleid = &tuple_ctid;			}			else if (estate->es_rowMark != NULL)			{				List	   *l;				execRowMark *erm;				Buffer		buffer;				HeapTupleData tuple;				TupleTableSlot *newSlot;				int			test;		lmark:	;				foreach(l, estate->es_rowMark)				{					erm = lfirst(l);					if (!ExecGetJunkAttribute(junkfilter,											  slot,											  erm->resname,											  &datum,											  &isNull))						elog(ERROR, "ExecutePlan: NO (junk) `%s' was found!", erm->resname);					if (isNull)						elog(ERROR, "ExecutePlan: (junk) `%s' is NULL!", erm->resname);					tuple.t_self = *((ItemPointer) DatumGetPointer(datum));					test = heap_mark4update(erm->relation, &tuple, &buffer);					ReleaseBuffer(buffer);					switch (test)					{						case HeapTupleSelfUpdated:						case HeapTupleMayBeUpdated:							break;						case HeapTupleUpdated:							if (XactIsoLevel == XACT_SERIALIZABLE)							{								elog(ERROR, "Can't serialize access due to concurrent update");								return (NULL);							}							else if (!(ItemPointerEquals(&(tuple.t_self),								  (ItemPointer) DatumGetPointer(datum))))							{								newSlot = EvalPlanQual(estate, erm->rti, &(tuple.t_self));								if (!(TupIsNull(newSlot)))								{									slot = newSlot;									estate->es_useEvalPlan = true;									goto lmark;								}							}							/*							 * if tuple was deleted or PlanQual failed for							 * updated tuple - we have not return this							 * tuple!							 */							goto lnext;						default:							elog(ERROR, "Unknown status %u from heap_mark4update", test);							return (NULL);					}				}			}			/*			 * Finally create a new "clean" tuple with all junk attributes			 * removed			 */			newTuple = ExecRemoveJunk(junkfilter, slot);			slot = ExecStoreTuple(newTuple,		/* tuple to store */								  slot, /* destination slot */								  InvalidBuffer,		/* this tuple has no														 * buffer */								  true);		/* tuple should be pfreed */		}						/* if (junkfilter... */		/*		 * now that we have a tuple, do the appropriate thing with it..		 * either return it to the user, add it to a relation someplace,		 * delete it from a relation, or modify some of it's attributes.		 */		switch (operation)		{			case CMD_SELECT:				ExecRetrieve(slot,		/* slot containing tuple */							 destfunc,	/* destination's tuple-receiver										 * obj */							 estate);	/* */				result = slot;				break;			case CMD_INSERT:				ExecAppend(slot, tupleid, estate);				result = NULL;				break;			case CMD_DELETE:				ExecDelete(slot, tupleid, estate);				result = NULL;				break;			case CMD_UPDATE:				ExecReplace(slot, tupleid, estate);				result = NULL;				break;			default:				elog(DEBUG, "ExecutePlan: unknown operation in queryDesc");				result = NULL;				break;		}		/*		 * check our tuple count.. if we've returned the proper number		 * then return, else loop again and process more tuples..		 */		current_tuple_count += 1;		if (numberTuples == current_tuple_count)			break;	}	/*	 * here, result is either a slot containing a tuple in the case of a	 * RETRIEVE or NULL otherwise.	 */	return result;}/* ---------------------------------------------------------------- *		ExecRetrieve * *		RETRIEVEs are easy.. we just pass the tuple to the appropriate *		print function.  The only complexity is when we do a *		"retrieve into", in which case we insert the tuple into *		the appropriate relation (note: this is a newly created relation *		so we don't need to worry about indices or locks.) * ---------------------------------------------------------------- */static voidExecRetrieve(TupleTableSlot *slot,			 DestReceiver *destfunc,			 EState *estate){	HeapTuple	tuple;	TupleDesc	attrtype;	/*	 * get the heap tuple out of the tuple table slot	 */	tuple = slot->val;	attrtype = slot->ttc_tupleDescriptor;	/*	 * insert the tuple into the "into relation"	 */	if (estate->es_into_relation_descriptor != NULL)	{		heap_insert(estate->es_into_relation_descriptor, tuple);		IncrAppended();	}	/*	 * send the tuple to the front end (or the screen)	 */	(*destfunc->receiveTuple) (tuple, attrtype, destfunc);	IncrRetrieved();	(estate->es_processed)++;}/* ---------------------------------------------------------------- *		ExecAppend * *		APPENDs are trickier.. we have to insert the tuple into *		the base relation and insert appropriate tuples into the *		index relations. * ---------------------------------------------------------------- */static voidExecAppend(TupleTableSlot *slot,		   ItemPointer tupleid,		   EState *estate){	HeapTuple	tuple;	RelationInfo *resultRelationInfo;	Relation	resultRelationDesc;	int			numIndices;	Oid			newId;	/*	 * get the heap tuple out of the tuple table slot	 */	tuple = slot->val;	/*	 * get information on the result relation	 */	resultRelationInfo = estate->es_result_relation_info;	resultRelationDesc = resultRelationInfo->ri_RelationDesc;	/*	 * have to add code to preform unique checking here. cim -12/1/89	 */	/* BEFORE ROW INSERT Triggers */	if (resultRelationDesc->trigdesc &&	resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)	{		HeapTuple	newtuple;		newtuple = ExecBRInsertTriggers(resultRelationDesc, tuple);		if (newtuple == NULL)	/* "do nothing" */			return;		if (newtuple != tuple)	/* modified by Trigger(s) */		{			Assert(slot->ttc_shouldFree);			pfree(tuple);			slot->val = tuple = newtuple;		}	}	/*	 * Check the constraints of a tuple	 */	if (resultRelationDesc->rd_att->constr)		ExecConstraints("ExecAppend", resultRelationDesc, tuple, estate);	/*	 * insert the tuple	 */	newId = heap_insert(resultRelationDesc,		/* relation desc */						tuple); /* heap tuple */	IncrAppended();	/*	 * process indices	 *	 * Note: heap_insert adds a new tuple to a relation.  As a side effect,	 * the tupleid of the new tuple is placed in the new tuple's t_ctid	 * field.	 */	numIndices = resultRelationInfo->ri_NumIndices;	if (numIndices > 0)		ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false);	(estate->es_processed)++;	estate->es_lastoid = newId;	/* AFTER ROW INSERT Triggers */	if (resultRelationDesc->trigdesc &&	 resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)		ExecARInsertTriggers(resultRelationDesc, tuple);}/* ---------------------------------------------------------------- *		ExecDelete * *		DELETE is like append, we delete the tuple and its *		index tuples. * ---------------------------------------------------------------- */static voidExecDelete(TupleTableSlot *slot,		   ItemPointer tupleid,		   EState *estate){	RelationInfo *resultRelationInfo;	Relation	resultRelationDesc;	ItemPointerData ctid;	int			result;	/*	 * get the result relation information	 */	resultRelationInfo = estate->es_result_relation_info;	resultRelationDesc = resultRelationInfo->ri_RelationDesc;	/* BEFORE ROW DELETE Triggers */	if (resultRelationDesc->trigdesc &&	resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_DELETE] > 0)	{		bool		dodelete;		dodelete = ExecBRDeleteTriggers(estate, tupleid);		if (!dodelete)			/* "do nothing" */			return;	}	/*	 * delete the tuple	 */ldelete:;	result = heap_delete(resultRelationDesc, tupleid, &ctid);	switch (result)	{		case HeapTupleSelfUpdated:			return;		case HeapTupleMayBeUpdated:			break;		case HeapTupleUpdated:			if (XactIsoLevel == XACT_SERIALIZABLE)				elog(ERROR, "Can't serialize access due to concurrent update");			else if (!(ItemPointerEquals(tupleid, &ctid)))			{				TupleTableSlot *epqslot = EvalPlanQual(estate,						  resultRelationInfo->ri_RangeTableIndex, &ctid);				if (!TupIsNull(epqslot))				{					*tupleid = ctid;					goto ldelete;				}			}			return;		default:			elog(ERROR, "Unknown status %u from heap_delete", result);			return;	}	IncrDeleted();	(estate->es_processed)++;	/*	 * Note: Normally one would think that we have to delete index tuples	 * associated with the heap tuple now..	 *	 * ... but in POSTGRES, we have no need to do this because the vacuum	 * daemon automatically opens an index scan and deletes index tuples	 * when it finds deleted heap tuples. -cim 9/27/89	 */	/* AFTER ROW DELETE Triggers */	if (resultRelationDesc->trigdesc &&	 resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)		ExecARDeleteTriggers(estate, tupleid);}/* ---------------------------------------------------------------- *		ExecReplace * *		note: we can't run replace queries with transactions *		off because replaces are actually appends and our *		scan will mistakenly loop forever, replacing the tuple *		it just appended..	This should be fixed but until it *		is, we don't want to get stuck in an infinite loop *		which corrupts your database.. * ---------------------------------------------------------------- */static voidExecReplace(TupleTableSlot *slot,			ItemPointer tupleid,			EState *estate){	HeapTuple	tuple;	RelationInfo *resultRelationInfo;	Relation	resultRelationDesc;	ItemPointerData ctid;	int			result;	int			numIndices;	/*	 * abort the operation if not running transactions	 */	if (IsBootstrapProcessingMode())	{		elog(DEBUG, "ExecReplace: replace can't run without transactions");		return;	}	/*	 * get the heap tuple out of the tuple table slot	 */	tuple = slot->val;	/*	 * get the result relation information	 */	resultRelationInfo = estate->es_result_relation_info;	resultRelationDesc = resultRelationInfo->ri_RelationDesc;	/*	 * have to add code to preform unique checking here. in the event of	 * unique tuples, this becomes a deletion of the original tuple	 * affected by the replace. cim -12/1/89	 */	/* BEFORE ROW UPDATE Triggers */	if (resultRelationDesc->trigdesc &&	resultRelationDesc->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0)	{		HeapTuple	newtuple;		newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);		if (newtuple == NULL)	/* "do nothing" */			return;		if (newtuple != tuple)	/* modified by Trigger(s) */		{			Assert(slot->ttc_shouldFree);			pfree(tuple);			slot->val = tuple = newtuple;		}	}	/*	 * Check the constraints of a tuple	 */	if (resultRelationDesc->rd_att->constr)		ExecConstraints("ExecReplace", resultRelationDesc, tuple, estate);	/*	 * replace the heap tuple	 */lreplace:;	result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid);	switch (result)	{		case HeapTupleSelfUpdated:			return;		case HeapTupleMayBeUpdated:			break;		case HeapTupleUpdated:			if (XactIsoLevel == XACT_SERIALIZABLE)				elog(ERROR, "Can't serialize access due to concurrent update");			else if (!(ItemPointerEquals(tupleid, &ctid)))			{				TupleTableSlot *epqslot = EvalPlanQual(estate,						  resultRelationInfo->ri_RangeTableIndex, &ctid);				if (!TupIsNull(epqslot))				{					*tupleid = ctid;					tuple = ExecRemoveJunk(estate->es_junkFilter, epqslot);

⌨️ 快捷键说明

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