返回顶部
首页 > 资讯 > 数据库 >PostgreSQL源码学习--删除数据#3
  • 709
分享到

PostgreSQL源码学习--删除数据#3

PostgreSQL源码学习--删除数据#3 2020-01-09 22:01:37 709人浏览 绘本
摘要

本节介绍ExecDelete函数。 从表中删除时,tupleid标识要删除的元组,oldtuple为空; 从视图中删除时,oldtuple传递给INSTEAD OF触发器标识要删除的内容,tupleid无效; 从外部表中删除时,tuplei

PostgreSQL源码学习--删除数据#3

本节介绍ExecDelete函数。

从表中删除时,tupleid标识要删除的元组,oldtuple为空;

从视图中删除时,oldtuple传递给INSTEAD OF触发器标识要删除的内容,tupleid无效;

从外部表中删除时,tupleid无效,fdw使用planslot中的数据找出要删除的行,oldtuple传递给外部表触发器。

tupleDeleted标识是否删除了元组。 如果这个删除操作是分区键更新的一部分,则EvalPlanQual会使用输出参数epqslot将slot返回。

函数返回值为RETURNING的结果结果。

ExecDelete函数

static TupleTableSlot *
ExecDelete(ModifyTableState *mtstate,
		   ItemPointer tupleid,
		   HeapTuple oldtuple,
		   TupleTableSlot *planSlot,
		   EPQState *epqstate,
		   EState *estate,
		   bool processReturning,
		   bool canSetTag,
		   bool changingPart,
		   bool *tupleDeleted,
		   TupleTableSlot **epqreturnslot);
//src/backend/executor/nodeModifyTable.c


if (tupleDeleted)
	*tupleDeleted = false;


resultRelInfo = estate->es_result_relation_info;
resultRelationDesc = resultRelInfo->ri_RelationDesc;


if (resultRelInfo->ri_TrigDesc &&
	resultRelInfo->ri_TrigDesc->trig_delete_before_row)
{
	bool		dodelete;

	dodelete = ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
							tupleid, oldtuple, epqreturnslot);

	if (!dodelete)		
		return NULL;
}


if (resultRelInfo->ri_TrigDesc &&
	resultRelInfo->ri_TrigDesc->trig_delete_instead_row)
{
	bool		dodelete;

	Assert(oldtuple != NULL);
	dodelete = ExecIRDeleteTriggers(estate, resultRelInfo, oldtuple);

	if (!dodelete)		
		return NULL;
}

else if (resultRelInfo->ri_FdwRoutine)
{
	
	slot = ExecGetReturningSlot(estate, resultRelInfo);
	slot = resultRelInfo->ri_FdwRoutine->ExecForeignDelete(estate,
								   resultRelInfo,
								   slot,
								   planSlot);

	if (slot == NULL)		
		return NULL;

	
	if (TTS_EMPTY(slot))
		ExecStoreAllNullTuple(slot);

	slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
}

else
{

ldelete:;
	
	result = table_tuple_delete(resultRelationDesc, tupleid,
						estate->es_output_cid,
						estate->es_snapshot,
						estate->es_crosscheck_snapshot,
						true  ,
						&tmfd,
						changingPart);
	
	switch (result)
	{
		
		case TM_SelfModified:
			if (tmfd.cmax != estate->es_output_cid)
				ereport(ERROR,
					(errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
					 errmsg("tuple to be deleted was already modified by an operation triggered by the current command"),
					 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));

			
			return NULL;
			
		
		case TM_Ok:
			break;
			
		
		case TM_Updated:
			{
				
				if (IsolationUsesXactSnapshot())
					ereport(ERROR,
							(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
							 errmsg("could not serialize access due to concurrent update")));
				
				
				EvalPlanQualBegin(epqstate);
				inputslot = EvalPlanQualSlot(epqstate, resultRelationDesc,
										 resultRelInfo->ri_RangeTableIndex);

				
				result = table_tuple_lock(resultRelationDesc, tupleid,
									  estate->es_snapshot,
									  inputslot, estate->es_output_cid,
									  LockTupleExclusive, LockWaitBlock,
									  TUPLE_LOCK_FLAG_FIND_LAST_VERSION,
									  &tmfd);
				
				switch (result)
				{
					case TM_Ok:
						Assert(tmfd.traversed);
						
						epqslot = EvalPlanQual(epqstate,
									   resultRelationDesc,
									   resultRelInfo->ri_RangeTableIndex,
									   inputslot);
						if (TupIsNull(epqslot))
							return NULL;
						
						
						if (epqreturnslot)
						{
							*epqreturnslot = epqslot;
							return NULL;
						}
						else
							goto ldelete;
					
					
					case TM_SelfModified:
						if (tmfd.cmax != estate->es_output_cid)
							ereport(ERROR,
									(errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
									 errmsg("tuple to be deleted was already modified by an operation triggered by the current command"),
									 errhint("Consider using an AFTER trigger instead of a BEFORE trigger to propagate changes to other rows.")));
						return NULL;
						
					
					case TM_Deleted:
						return NULL;
						
					
					default:
						elog(ERROR, "unexpected table_tuple_lock status: %u",
							 result);
						return NULL;
				}
				
				Assert(false);
				break;
			}
			
		
		case TM_Deleted:
			if (IsolationUsesXactSnapshot())
				ereport(ERROR,
						(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
						 errmsg("could not serialize access due to concurrent delete")));
			return NULL;
			
		
		default:
			elog(ERROR, "unrecognized table_tuple_delete status: %u",
				 result);
			return NULL;
	}
	
}


if (canSetTag)
	(estate->es_processed)++;


if (tupleDeleted)
	*tupleDeleted = true;


ar_delete_trig_tcs = mtstate->mt_transition_capture;
if (mtstate->operation == CMD_UPDATE && mtstate->mt_transition_capture
	&& mtstate->mt_transition_capture->tcs_update_old_table)
{
	ExecARUpdateTriggers(estate, resultRelInfo,
					 tupleid,
					 oldtuple,
					 NULL,
					 NULL,
					 mtstate->mt_transition_capture);
	
	
	ar_delete_trig_tcs = NULL;
}


ExecARDeleteTriggers(estate, resultRelInfo, tupleid, oldtuple,
				 ar_delete_trig_tcs);


if (processReturning && resultRelInfo->ri_projectReturning)
{
	
	if (resultRelInfo->ri_FdwRoutine)
	{
		
		Assert(!TupIsNull(slot));
	}
	else
	{
		slot = ExecGetReturningSlot(estate, resultRelInfo);
		if (oldtuple != NULL)
		{
			ExecForceStoreHeapTuple(oldtuple, slot, false);
		}
		else
		{
			if (!table_tuple_fetch_row_version(resultRelationDesc, tupleid,
										   SnapshotAny, slot))
				elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING");
		}
	}
	rslot = ExecProcessReturning(resultRelInfo, slot, planSlot);
	
	
	ExecMaterializeSlot(rslot);
	
	ExecClearTuple(slot);

	return rslot;
}

return NULL;
您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL源码学习--删除数据#3

本文链接: https://lsjlt.com/news/6562.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作