广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL源码学习--更新数据#3
  • 462
分享到

PostgreSQL源码学习--更新数据#3

PostgreSQL源码学习--更新数据#3 2016-11-30 01:11:57 462人浏览 猪猪侠
摘要

本节介绍ExecUpdate函数。 ExecUpdate函数 static TupleTableSlot * ExecUpdate(ModifyTableState *mtstate, ItemPointer tupleid,

PostgreSQL源码学习--更新数据#3

本节介绍ExecUpdate函数。

ExecUpdate函数

static TupleTableSlot *
ExecUpdate(ModifyTableState *mtstate,
		   ItemPointer tupleid,
		   HeapTuple oldtuple,
		   TupleTableSlot *slot,
		   TupleTableSlot *planSlot,
		   EPQState *epqstate,
		   EState *estate,
		   bool canSetTag);

if (IsBootstrapProcessingMode())
	elog(ERROR, "cannot UPDATE during bootstrap");

ExecMaterializeSlot(slot);


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


if (resultRelInfo->ri_TrigDesc &&
	resultRelInfo->ri_TrigDesc->trig_update_before_row)
{
	if (!ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
						  tupleid, oldtuple, slot))
		return NULL;		
}


if (resultRelInfo->ri_TrigDesc &&
	resultRelInfo->ri_TrigDesc->trig_update_instead_row)
{
	if (!ExecIRUpdateTriggers(estate, resultRelInfo,
						  oldtuple, slot))
		return NULL;		
}

else if (resultRelInfo->ri_FdwRoutine)
{
	
	if (resultRelationDesc->rd_att->constr &&
		resultRelationDesc->rd_att->constr->has_generated_stored)
		ExecComputeStoredGenerated(estate, slot);
	
	
	slot = resultRelInfo->ri_FdwRoutine->ExecForeignUpdate(estate,
								   resultRelInfo,
								   slot,
								   planSlot);
	
	if (slot == NULL)	
		return NULL;
	
	
	slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
}

else
{
	
	slot->tts_tableOid = RelationGetRelid(resultRelationDesc);
	
	
	if (resultRelationDesc->rd_att->constr &&
		resultRelationDesc->rd_att->constr->has_generated_stored)
		ExecComputeStoredGenerated(estate, slot);
	

lreplace:
	
	ExecMaterializeSlot(slot);
	
	
	partition_constraint_failed =
		resultRelInfo->ri_PartitionCheck &&
		!ExecPartitionCheck(resultRelInfo, slot, estate, false);
	
	
	if (!partition_constraint_failed &&
		resultRelInfo->ri_WithCheckOptions != NIL)
	{
		ExecWithCheckOptions(WCO_RLS_UPDATE_CHECK,
					 resultRelInfo, slot, estate);
	}
	
	
	if (partition_constraint_failed)
	{
		PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
		
		
		if (((ModifyTable *) mtstate->ps.plan)->onConflictAction == ONCONFLICT_UPDATE)
			ereport(ERROR,
					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
					 errmsg("invalid ON UPDATE specification"),
					 errdetail("The result tuple would appear in a different partition than the original tuple.")));
		
		
		if (proute == NULL)
			ExecPartitionCheckEmitError(resultRelInfo, slot, estate);
		
		
		ExecDelete(mtstate, tupleid, oldtuple, planSlot, epqstate,
				   estate, false, false  ,
				   true  , &tuple_deleted, &epqslot);
		
		
		if (!tuple_deleted)
		{
			
			if (TupIsNull(epqslot))
				return NULL;
			else
			{
				slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot);
				goto lreplace;
			}
		}
		
		
		if (mtstate->mt_transition_capture)
			saved_tcs_map = mtstate->mt_transition_capture->tcs_map;
		
		
		map_index = resultRelInfo - mtstate->resultRelInfo;
		Assert(map_index >= 0 && map_index < mtstate->mt_nplans);
		tupconv_map = tupconv_map_for_subplan(mtstate, map_index);
		if (tupconv_map != NULL)
			slot = execute_attr_map_slot(tupconv_map->attrMap,
							 slot,
							 mtstate->mt_root_tuple_slot);
		
		
		Assert(mtstate->rootResultRelInfo != NULL);
		slot = ExecPrepareTupleRouting(mtstate, estate, proute,
						   mtstate->rootResultRelInfo, slot);
		
		
		ret_slot = ExecInsert(mtstate, slot, planSlot,
								  estate, canSetTag);
		
		
		estate->es_result_relation_info = resultRelInfo;
		if (mtstate->mt_transition_capture)
		{
			mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL;
			mtstate->mt_transition_capture->tcs_map = saved_tcs_map;
		}
		
		
		return ret_slot;
	}
	
	
	if (resultRelationDesc->rd_att->constr)
		ExecConstraints(resultRelInfo, slot, estate);
	
	
	result = table_tuple_update(resultRelationDesc, tupleid, slot,
						estate->es_output_cid,
						estate->es_snapshot,
						estate->es_crosscheck_snapshot,
						true  ,
						&tmfd, &lockmode, &update_indexes);
	
	switch (result)
	{
		
		case TM_SelfModified:
			if (tmfd.cmax != estate->es_output_cid)
				ereport(ERROR,
						(errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
						 errmsg("tuple to be updated 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")));
				
				
				inputslot = EvalPlanQualSlot(epqstate, resultRelationDesc,
									 resultRelInfo->ri_RangeTableIndex);

				result = table_tuple_lock(resultRelationDesc, tupleid,
								  estate->es_snapshot,
								  inputslot, estate->es_output_cid,
								  lockmode, 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;
						
						slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot);
							goto lreplace;
						
					
					case TM_Deleted:
						return NULL;
						
					
					case TM_SelfModified:
						if (tmfd.cmax != estate->es_output_cid)
							ereport(ERROR,
								(errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
								 errmsg("tuple to be updated 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;
						
					
					default:
						elog(ERROR, "unexpected table_tuple_lock status: %u",
							 result);
						return NULL;
				}
			}
			
			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_update status: %u",
					 result);
			return NULL;
	}
	
	
	if (resultRelInfo->ri_NumIndices > 0 && update_indexes)
		recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, NIL);
}


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


ExecARUpdateTriggers(estate, resultRelInfo, tupleid, oldtuple, slot,
				 recheckIndexes,
				 mtstate->operation == CMD_INSERT ?
				 mtstate->mt_oc_transition_capture :
				 mtstate->mt_transition_capture);

list_free(recheckIndexes);


if (resultRelInfo->ri_WithCheckOptions != NIL)
	ExecWithCheckOptions(WCO_VIEW_CHECK, resultRelInfo, slot, estate);


if (resultRelInfo->ri_projectReturning)
	return ExecProcessReturning(resultRelInfo, slot, planSlot);

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

--结束END--

本文标题: PostgreSQL源码学习--更新数据#3

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

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

  • 微信公众号

  • 商务合作