Skip to content

Commit

Permalink
Implement In-Place Update for DML node
Browse files Browse the repository at this point in the history
Added the exec Update call in the DML node. Added partitioning selection in case
of In-Place update by sorted table. added a call to reconstructMatchingTupleSlot
in execUpdate to update plans generated by ORCA to handle cases of dropped
attributes.
  • Loading branch information
KnightMurloc committed Jan 15, 2024
1 parent e730004 commit 30956b8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 23 deletions.
61 changes: 41 additions & 20 deletions src/backend/executor/nodeDML.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,17 @@ ExecDML(DMLState *node)
}

bool isnull = false;
int action = DatumGetUInt32(slot_getattr(slot, plannode->actionColIdx, &isnull));
Assert(!isnull);

bool isUpdate = false;
if (node->ps.state->es_plannedstmt->commandType == CMD_UPDATE)
int action = -1;
bool isUpdate = node->ps.state->es_plannedstmt->commandType == CMD_UPDATE;
// if it's not in place update
if (AttributeNumberIsValid(plannode->actionColIdx))
{
isUpdate = true;
action = DatumGetUInt32(
slot_getattr(slot, plannode->actionColIdx, &isnull));
Assert(!isnull);
Assert(action == DML_INSERT || action == DML_DELETE);
}

Assert(action == DML_INSERT || action == DML_DELETE);


/*
* Reset per-tuple memory context to free any expression evaluation
* storage allocated in the previous tuple cycle.
Expand Down Expand Up @@ -116,6 +115,13 @@ ExecDML(DMLState *node)
* es_result_relations will contain the only relation.
*/
node->ps.state->es_result_relation_info = relInfo;

/*
* Perform partition selection for in place update
*/
if (isUpdate && !AttributeNumberIsValid(plannode->actionColIdx))
node->ps.state->es_result_relation_info =
slot_get_partition(node->cleanedUpSlot, node->ps.state);
}
/* GPDB_91_MERGE_FIXME:
* This kind of node is used by ORCA only. If in the future ORCA still uses
Expand Down Expand Up @@ -155,7 +161,7 @@ ExecDML(DMLState *node)
isUpdate,
InvalidOid);
}
else /* DML_DELETE */
else
{
int32 segid = GpIdentity.segindex;
Datum ctid = slot_getattr(slot, plannode->ctidColIdx, &isnull);
Expand All @@ -172,16 +178,31 @@ ExecDML(DMLState *node)
Assert(!isnull);
}

/* Correct tuple count by ignoring deletes when splitting tuples. */
ExecDelete(tupleid,
segid,
NULL, /* GPDB_91_MERGE_FIXME: oldTuple? */
node->cleanedUpSlot,
NULL /* DestReceiver */,
node->ps.state,
!isUpdate, /* GPDB_91_MERGE_FIXME: where to get canSetTag? */
PLANGEN_OPTIMIZER /* Plan origin */,
isUpdate);
if (DML_DELETE == action)
{
/* Correct tuple count by ignoring deletes when splitting tuples. */
ExecDelete(tupleid,
segid,
NULL, /* GPDB_91_MERGE_FIXME: oldTuple? */
node->cleanedUpSlot,
NULL /* DestReceiver */,
node->ps.state,
!isUpdate, /* GPDB_91_MERGE_FIXME: where to get canSetTag? */
PLANGEN_OPTIMIZER /* Plan origin */,
isUpdate);
}
else
{
ExecUpdate(tupleid,
segid,
NULL, //oldtuple
node->cleanedUpSlot,
NULL, //planSlot
NULL /* DestReceiver */,
node->ps.state,
true,
PLANGEN_OPTIMIZER);
}
}

return slot;
Expand Down
20 changes: 18 additions & 2 deletions src/backend/executor/nodeModifyTable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1301,7 +1301,8 @@ ExecUpdate(ItemPointer tupleid,
TupleTableSlot *planSlot,
EPQState *epqstate,
EState *estate,
bool canSetTag)
bool canSetTag,
PlanGenerator planGen)
{
ResultRelInfo *resultRelInfo;
Relation resultRelationDesc;
Expand Down Expand Up @@ -1370,8 +1371,12 @@ ExecUpdate(ItemPointer tupleid,

/* see if this update would move the tuple to a different partition */
if (estate->es_result_partitions)
{
checkPartitionUpdate(estate, slot, resultRelInfo);

if (planGen == PLANGEN_OPTIMIZER)
slot = reconstructMatchingTupleSlot(slot, resultRelInfo);
}
/* BEFORE ROW UPDATE Triggers */
if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->trig_update_before_row)
Expand Down Expand Up @@ -1571,6 +1576,17 @@ lreplace:;
{
TupleTableSlot *epqslot;

/*
* TODO: DML node doesn't initialize `epqstate` parameter so
* we exclude EPQ routine for this type of modification and
* act as in RR and upper isolation levels.
*/
if (!epqstate)
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update"),
errhint("Use PostgreSQL Planner instead of Optimizer for this query via optimizer=off GUC setting")));

epqslot = EvalPlanQual(estate,
epqstate,
resultRelationDesc,
Expand Down Expand Up @@ -1942,7 +1958,7 @@ ExecModifyTable(ModifyTableState *node)
slot = ExecUpdate(tupleid, segid,
oldtuple, slot, planSlot,
&node->mt_epqstate, estate,
node->canSetTag);
node->canSetTag, PLANGEN_PLANNER);
break;
}

Expand Down
3 changes: 2 additions & 1 deletion src/include/executor/execDML.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ ExecUpdate(ItemPointer tupleid,
TupleTableSlot *planSlot,
EPQState *epqstate,
EState *estate,
bool canSetTag);
bool canSetTag,
PlanGenerator planGen);


#endif /* EXECDML_H */
Expand Down

0 comments on commit 30956b8

Please sign in to comment.