static HeapTuple update_entity_tuple()

in src/backend/executor/cypher_set.c [92:185]


static HeapTuple update_entity_tuple(ResultRelInfo *resultRelInfo,
                                     TupleTableSlot *elemTupleSlot,
                                     EState *estate, HeapTuple old_tuple)
{
    HeapTuple tuple = NULL;
    LockTupleMode lockmode;
    TM_FailureData hufd;
    TM_Result lock_result;
    Buffer buffer;
    TU_UpdateIndexes update_indexes;
    TM_Result   result;
    CommandId cid = GetCurrentCommandId(true);
    ResultRelInfo **saved_resultRels = estate->es_result_relations;

    estate->es_result_relations = &resultRelInfo;

    lockmode = ExecUpdateLockMode(estate, resultRelInfo);

    lock_result = heap_lock_tuple(resultRelInfo->ri_RelationDesc, old_tuple,
                                  GetCurrentCommandId(false), lockmode,
                                  LockWaitBlock, false, &buffer, &hufd);

    if (lock_result == TM_Ok)
    {
        ExecOpenIndices(resultRelInfo, false);
        ExecStoreVirtualTuple(elemTupleSlot);
        tuple = ExecFetchSlotHeapTuple(elemTupleSlot, true, NULL);
        tuple->t_self = old_tuple->t_self;

        /* Check the constraints of the tuple */
        tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
        if (resultRelInfo->ri_RelationDesc->rd_att->constr != NULL)
        {
            ExecConstraints(resultRelInfo, elemTupleSlot, estate);
        }

        result = table_tuple_update(resultRelInfo->ri_RelationDesc,
                                    &tuple->t_self, elemTupleSlot,
                                    cid, estate->es_snapshot,
                                    estate->es_crosscheck_snapshot,
                                    true /* wait for commit */ ,
                                    &hufd, &lockmode, &update_indexes);

        if (result == TM_SelfModified)
        {
            if (hufd.cmax != cid)
            {
                ereport(ERROR,
                        (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
                         errmsg("tuple to be updated was already modified")));
            }

            ExecCloseIndices(resultRelInfo);
            estate->es_result_relations = saved_resultRels;

            return tuple;
        }

        if (result != TM_Ok)
        {
            ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
                    errmsg("Entity failed to be updated: %i", result)));
        }

        /* Insert index entries for the tuple */
        if (resultRelInfo->ri_NumIndices > 0 && update_indexes != TU_None)
        {
          ExecInsertIndexTuples(resultRelInfo, elemTupleSlot, estate, false, false, NULL, NIL,
                                (update_indexes == TU_Summarizing));
        }

        ExecCloseIndices(resultRelInfo);
    }
    else if (lock_result == TM_SelfModified)
    {
        if (hufd.cmax != cid)
        {
            ereport(ERROR,
                    (errcode(ERRCODE_TRIGGERED_DATA_CHANGE_VIOLATION),
                     errmsg("tuple to be updated was already modified")));
        }
    }
    else
    {
        ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR),
                errmsg("Entity failed to be updated: %i", lock_result)));
    }

    ReleaseBuffer(buffer);

    estate->es_result_relations = saved_resultRels;

    return tuple;
}