本节介绍ExecDelete函数。 从表中删除时,tupleid标识要删除的元组,oldtuple为空; 从视图中删除时,oldtuple传递给INSTEAD OF触发器标识要删除的内容,tupleid无效; 从外部表中删除时,tuplei
本节介绍ExecDelete函数。
从表中删除时,tupleid标识要删除的元组,oldtuple为空;
从视图中删除时,oldtuple传递给INSTEAD OF触发器标识要删除的内容,tupleid无效;
从外部表中删除时,tupleid无效,fdw使用planslot中的数据找出要删除的行,oldtuple传递给外部表触发器。
tupleDeleted标识是否删除了元组。 如果这个删除操作是分区键更新的一部分,则EvalPlanQual会使用输出参数epqslot将slot返回。
函数返回值为RETURNING的结果结果。
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
2024-10-23
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
2024-10-22
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0