Remove es_result_relation_info from EState.

Maintaining 'es_result_relation_info' correctly at all times has become
cumbersome, especially with partitioning where each partition gets its
own result relation info. Having to set and reset it across arbitrary
operations has caused bugs in the past.

This changes all the places that used 'es_result_relation_info', to
receive the currently active ResultRelInfo via function parameters
instead.

Author: Amit Langote
Discussion: https://www.postgresql.org/message-id/CA%2BHiwqGEmiib8FLiHMhKB%2BCH5dRgHSLc5N5wnvc4kym%2BZYpQEQ%40mail.gmail.com
This commit is contained in:
Heikki Linnakangas 2020-10-14 11:41:40 +03:00
parent 178f2d560d
commit a04daa97a4
13 changed files with 131 additions and 177 deletions

View File

@ -2489,9 +2489,6 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
ResultRelInfo *resultRelInfo = buffer->resultRelInfo; ResultRelInfo *resultRelInfo = buffer->resultRelInfo;
TupleTableSlot **slots = buffer->slots; TupleTableSlot **slots = buffer->slots;
/* Set es_result_relation_info to the ResultRelInfo we're flushing. */
estate->es_result_relation_info = resultRelInfo;
/* /*
* Print error context information correctly, if one of the operations * Print error context information correctly, if one of the operations
* below fail. * below fail.
@ -2524,7 +2521,8 @@ CopyMultiInsertBufferFlush(CopyMultiInsertInfo *miinfo,
cstate->cur_lineno = buffer->linenos[i]; cstate->cur_lineno = buffer->linenos[i];
recheckIndexes = recheckIndexes =
ExecInsertIndexTuples(buffer->slots[i], estate, false, NULL, ExecInsertIndexTuples(resultRelInfo,
buffer->slots[i], estate, false, NULL,
NIL); NIL);
ExecARInsertTriggers(estate, resultRelInfo, ExecARInsertTriggers(estate, resultRelInfo,
slots[i], recheckIndexes, slots[i], recheckIndexes,
@ -2839,8 +2837,6 @@ CopyFrom(CopyState cstate)
ExecOpenIndices(resultRelInfo, false); ExecOpenIndices(resultRelInfo, false);
estate->es_result_relation_info = resultRelInfo;
/* /*
* Set up a ModifyTableState so we can let FDW(s) init themselves for * Set up a ModifyTableState so we can let FDW(s) init themselves for
* foreign-table result relation(s). * foreign-table result relation(s).
@ -3108,11 +3104,6 @@ CopyFrom(CopyState cstate)
prevResultRelInfo = resultRelInfo; prevResultRelInfo = resultRelInfo;
} }
/*
* For ExecInsertIndexTuples() to work on the partition's indexes
*/
estate->es_result_relation_info = resultRelInfo;
/* /*
* If we're capturing transition tuples, we might need to convert * If we're capturing transition tuples, we might need to convert
* from the partition rowtype to root rowtype. * from the partition rowtype to root rowtype.
@ -3217,7 +3208,8 @@ CopyFrom(CopyState cstate)
/* Compute stored generated columns */ /* Compute stored generated columns */
if (resultRelInfo->ri_RelationDesc->rd_att->constr && if (resultRelInfo->ri_RelationDesc->rd_att->constr &&
resultRelInfo->ri_RelationDesc->rd_att->constr->has_generated_stored) resultRelInfo->ri_RelationDesc->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, myslot, CMD_INSERT); ExecComputeStoredGenerated(resultRelInfo, estate, myslot,
CMD_INSERT);
/* /*
* If the target is a plain table, check the constraints of * If the target is a plain table, check the constraints of
@ -3288,7 +3280,8 @@ CopyFrom(CopyState cstate)
myslot, mycid, ti_options, bistate); myslot, mycid, ti_options, bistate);
if (resultRelInfo->ri_NumIndices > 0) if (resultRelInfo->ri_NumIndices > 0)
recheckIndexes = ExecInsertIndexTuples(myslot, recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
myslot,
estate, estate,
false, false,
NULL, NULL,

View File

@ -1820,7 +1820,6 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
resultRelInfo = resultRelInfos; resultRelInfo = resultRelInfos;
foreach(cell, rels) foreach(cell, rels)
{ {
estate->es_result_relation_info = resultRelInfo;
ExecBSTruncateTriggers(estate, resultRelInfo); ExecBSTruncateTriggers(estate, resultRelInfo);
resultRelInfo++; resultRelInfo++;
} }
@ -1950,7 +1949,6 @@ ExecuteTruncateGuts(List *explicit_rels, List *relids, List *relids_logged,
resultRelInfo = resultRelInfos; resultRelInfo = resultRelInfos;
foreach(cell, rels) foreach(cell, rels)
{ {
estate->es_result_relation_info = resultRelInfo;
ExecASTruncateTriggers(estate, resultRelInfo); ExecASTruncateTriggers(estate, resultRelInfo);
resultRelInfo++; resultRelInfo++;
} }

View File

@ -270,7 +270,8 @@ ExecCloseIndices(ResultRelInfo *resultRelInfo)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
List * List *
ExecInsertIndexTuples(TupleTableSlot *slot, ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot,
EState *estate, EState *estate,
bool noDupErr, bool noDupErr,
bool *specConflict, bool *specConflict,
@ -278,7 +279,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
{ {
ItemPointer tupleid = &slot->tts_tid; ItemPointer tupleid = &slot->tts_tid;
List *result = NIL; List *result = NIL;
ResultRelInfo *resultRelInfo;
int i; int i;
int numIndices; int numIndices;
RelationPtr relationDescs; RelationPtr relationDescs;
@ -293,7 +293,6 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
/* /*
* Get information from the result relation info structure. * Get information from the result relation info structure.
*/ */
resultRelInfo = estate->es_result_relation_info;
numIndices = resultRelInfo->ri_NumIndices; numIndices = resultRelInfo->ri_NumIndices;
relationDescs = resultRelInfo->ri_IndexRelationDescs; relationDescs = resultRelInfo->ri_IndexRelationDescs;
indexInfoArray = resultRelInfo->ri_IndexRelationInfo; indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
@ -479,11 +478,10 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool bool
ExecCheckIndexConstraints(TupleTableSlot *slot, ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo, TupleTableSlot *slot,
EState *estate, ItemPointer conflictTid, EState *estate, ItemPointer conflictTid,
List *arbiterIndexes) List *arbiterIndexes)
{ {
ResultRelInfo *resultRelInfo;
int i; int i;
int numIndices; int numIndices;
RelationPtr relationDescs; RelationPtr relationDescs;
@ -501,7 +499,6 @@ ExecCheckIndexConstraints(TupleTableSlot *slot,
/* /*
* Get information from the result relation info structure. * Get information from the result relation info structure.
*/ */
resultRelInfo = estate->es_result_relation_info;
numIndices = resultRelInfo->ri_NumIndices; numIndices = resultRelInfo->ri_NumIndices;
relationDescs = resultRelInfo->ri_IndexRelationDescs; relationDescs = resultRelInfo->ri_IndexRelationDescs;
indexInfoArray = resultRelInfo->ri_IndexRelationInfo; indexInfoArray = resultRelInfo->ri_IndexRelationInfo;

View File

@ -827,9 +827,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
estate->es_plannedstmt = plannedstmt; estate->es_plannedstmt = plannedstmt;
/* es_result_relation_info is NULL except when within ModifyTable */
estate->es_result_relation_info = NULL;
/* /*
* Next, build the ExecRowMark array from the PlanRowMark(s), if any. * Next, build the ExecRowMark array from the PlanRowMark(s), if any.
*/ */
@ -2694,7 +2691,6 @@ EvalPlanQualStart(EPQState *epqstate, Plan *planTree)
* subplans themselves are initialized. * subplans themselves are initialized.
*/ */
parentestate->es_result_relations = NULL; parentestate->es_result_relations = NULL;
/* es_result_relation_info must NOT be copied */
/* es_trig_target_relations must NOT be copied */ /* es_trig_target_relations must NOT be copied */
rcestate->es_top_eflags = parentestate->es_top_eflags; rcestate->es_top_eflags = parentestate->es_top_eflags;
rcestate->es_instrument = parentestate->es_instrument; rcestate->es_instrument = parentestate->es_instrument;

View File

@ -404,10 +404,10 @@ retry:
* Caller is responsible for opening the indexes. * Caller is responsible for opening the indexes.
*/ */
void void
ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot) ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo,
EState *estate, TupleTableSlot *slot)
{ {
bool skip_tuple = false; bool skip_tuple = false;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc; Relation rel = resultRelInfo->ri_RelationDesc;
/* For now we support only tables. */ /* For now we support only tables. */
@ -430,7 +430,8 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
/* Compute stored generated columns */ /* Compute stored generated columns */
if (rel->rd_att->constr && if (rel->rd_att->constr &&
rel->rd_att->constr->has_generated_stored) rel->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, slot, CMD_INSERT); ExecComputeStoredGenerated(resultRelInfo, estate, slot,
CMD_INSERT);
/* Check the constraints of the tuple */ /* Check the constraints of the tuple */
if (rel->rd_att->constr) if (rel->rd_att->constr)
@ -442,7 +443,8 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot); simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot);
if (resultRelInfo->ri_NumIndices > 0) if (resultRelInfo->ri_NumIndices > 0)
recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
slot, estate, false, NULL,
NIL); NIL);
/* AFTER ROW INSERT Triggers */ /* AFTER ROW INSERT Triggers */
@ -466,11 +468,11 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
* Caller is responsible for opening the indexes. * Caller is responsible for opening the indexes.
*/ */
void void
ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo,
EState *estate, EPQState *epqstate,
TupleTableSlot *searchslot, TupleTableSlot *slot) TupleTableSlot *searchslot, TupleTableSlot *slot)
{ {
bool skip_tuple = false; bool skip_tuple = false;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc; Relation rel = resultRelInfo->ri_RelationDesc;
ItemPointer tid = &(searchslot->tts_tid); ItemPointer tid = &(searchslot->tts_tid);
@ -496,7 +498,8 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
/* Compute stored generated columns */ /* Compute stored generated columns */
if (rel->rd_att->constr && if (rel->rd_att->constr &&
rel->rd_att->constr->has_generated_stored) rel->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, slot, CMD_UPDATE); ExecComputeStoredGenerated(resultRelInfo, estate, slot,
CMD_UPDATE);
/* Check the constraints of the tuple */ /* Check the constraints of the tuple */
if (rel->rd_att->constr) if (rel->rd_att->constr)
@ -508,7 +511,8 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
&update_indexes); &update_indexes);
if (resultRelInfo->ri_NumIndices > 0 && update_indexes) if (resultRelInfo->ri_NumIndices > 0 && update_indexes)
recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
slot, estate, false, NULL,
NIL); NIL);
/* AFTER ROW UPDATE Triggers */ /* AFTER ROW UPDATE Triggers */
@ -527,11 +531,11 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
* Caller is responsible for opening the indexes. * Caller is responsible for opening the indexes.
*/ */
void void
ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo,
EState *estate, EPQState *epqstate,
TupleTableSlot *searchslot) TupleTableSlot *searchslot)
{ {
bool skip_tuple = false; bool skip_tuple = false;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc; Relation rel = resultRelInfo->ri_RelationDesc;
ItemPointer tid = &searchslot->tts_tid; ItemPointer tid = &searchslot->tts_tid;

View File

@ -125,7 +125,6 @@ CreateExecutorState(void)
estate->es_result_relations = NULL; estate->es_result_relations = NULL;
estate->es_opened_result_relations = NIL; estate->es_opened_result_relations = NIL;
estate->es_result_relation_info = NULL;
estate->es_tuple_routing_result_relations = NIL; estate->es_tuple_routing_result_relations = NIL;
estate->es_trig_target_relations = NIL; estate->es_trig_target_relations = NIL;

View File

@ -70,7 +70,8 @@ static TupleTableSlot *ExecPrepareTupleRouting(ModifyTableState *mtstate,
EState *estate, EState *estate,
PartitionTupleRouting *proute, PartitionTupleRouting *proute,
ResultRelInfo *targetRelInfo, ResultRelInfo *targetRelInfo,
TupleTableSlot *slot); TupleTableSlot *slot,
ResultRelInfo **partRelInfo);
static ResultRelInfo *getTargetResultRelInfo(ModifyTableState *node); static ResultRelInfo *getTargetResultRelInfo(ModifyTableState *node);
static void ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate); static void ExecSetupChildParentMapForSubplan(ModifyTableState *mtstate);
static TupleConversionMap *tupconv_map_for_subplan(ModifyTableState *node, static TupleConversionMap *tupconv_map_for_subplan(ModifyTableState *node,
@ -246,9 +247,10 @@ ExecCheckTIDVisible(EState *estate,
* Compute stored generated columns for a tuple * Compute stored generated columns for a tuple
*/ */
void void
ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype) ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
EState *estate, TupleTableSlot *slot,
CmdType cmdtype)
{ {
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
Relation rel = resultRelInfo->ri_RelationDesc; Relation rel = resultRelInfo->ri_RelationDesc;
TupleDesc tupdesc = RelationGetDescr(rel); TupleDesc tupdesc = RelationGetDescr(rel);
int natts = tupdesc->natts; int natts = tupdesc->natts;
@ -366,32 +368,48 @@ ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype
* ExecInsert * ExecInsert
* *
* For INSERT, we have to insert the tuple into the target relation * For INSERT, we have to insert the tuple into the target relation
* and insert appropriate tuples into the index relations. * (or partition thereof) and insert appropriate tuples into the index
* relations.
* *
* Returns RETURNING result if any, otherwise NULL. * Returns RETURNING result if any, otherwise NULL.
*
* This may change the currently active tuple conversion map in
* mtstate->mt_transition_capture, so the callers must take care to
* save the previous value to avoid losing track of it.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleTableSlot * static TupleTableSlot *
ExecInsert(ModifyTableState *mtstate, ExecInsert(ModifyTableState *mtstate,
ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, TupleTableSlot *slot,
TupleTableSlot *planSlot, TupleTableSlot *planSlot,
EState *estate, EState *estate,
bool canSetTag) bool canSetTag)
{ {
ResultRelInfo *resultRelInfo;
Relation resultRelationDesc; Relation resultRelationDesc;
List *recheckIndexes = NIL; List *recheckIndexes = NIL;
TupleTableSlot *result = NULL; TupleTableSlot *result = NULL;
TransitionCaptureState *ar_insert_trig_tcs; TransitionCaptureState *ar_insert_trig_tcs;
ModifyTable *node = (ModifyTable *) mtstate->ps.plan; ModifyTable *node = (ModifyTable *) mtstate->ps.plan;
OnConflictAction onconflict = node->onConflictAction; OnConflictAction onconflict = node->onConflictAction;
PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
/*
* If the input result relation is a partitioned table, find the leaf
* partition to insert the tuple into.
*/
if (proute)
{
ResultRelInfo *partRelInfo;
slot = ExecPrepareTupleRouting(mtstate, estate, proute,
resultRelInfo, slot,
&partRelInfo);
resultRelInfo = partRelInfo;
}
ExecMaterializeSlot(slot); ExecMaterializeSlot(slot);
/*
* get information on the (current) result relation
*/
resultRelInfo = estate->es_result_relation_info;
resultRelationDesc = resultRelInfo->ri_RelationDesc; resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* /*
@ -424,7 +442,8 @@ ExecInsert(ModifyTableState *mtstate,
*/ */
if (resultRelationDesc->rd_att->constr && if (resultRelationDesc->rd_att->constr &&
resultRelationDesc->rd_att->constr->has_generated_stored) resultRelationDesc->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, slot, CMD_INSERT); ExecComputeStoredGenerated(resultRelInfo, estate, slot,
CMD_INSERT);
/* /*
* insert into foreign table: let the FDW do it * insert into foreign table: let the FDW do it
@ -459,7 +478,8 @@ ExecInsert(ModifyTableState *mtstate,
*/ */
if (resultRelationDesc->rd_att->constr && if (resultRelationDesc->rd_att->constr &&
resultRelationDesc->rd_att->constr->has_generated_stored) resultRelationDesc->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, slot, CMD_INSERT); ExecComputeStoredGenerated(resultRelInfo, estate, slot,
CMD_INSERT);
/* /*
* Check any RLS WITH CHECK policies. * Check any RLS WITH CHECK policies.
@ -521,8 +541,8 @@ ExecInsert(ModifyTableState *mtstate,
*/ */
vlock: vlock:
specConflict = false; specConflict = false;
if (!ExecCheckIndexConstraints(slot, estate, &conflictTid, if (!ExecCheckIndexConstraints(resultRelInfo, slot, estate,
arbiterIndexes)) &conflictTid, arbiterIndexes))
{ {
/* committed conflict tuple found */ /* committed conflict tuple found */
if (onconflict == ONCONFLICT_UPDATE) if (onconflict == ONCONFLICT_UPDATE)
@ -582,7 +602,8 @@ ExecInsert(ModifyTableState *mtstate,
specToken); specToken);
/* insert index entries for tuple */ /* insert index entries for tuple */
recheckIndexes = ExecInsertIndexTuples(slot, estate, true, recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
slot, estate, true,
&specConflict, &specConflict,
arbiterIndexes); arbiterIndexes);
@ -621,8 +642,9 @@ ExecInsert(ModifyTableState *mtstate,
/* insert index entries for tuple */ /* insert index entries for tuple */
if (resultRelInfo->ri_NumIndices > 0) if (resultRelInfo->ri_NumIndices > 0)
recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
NIL); slot, estate, false,
NULL, NIL);
} }
} }
@ -707,6 +729,7 @@ ExecInsert(ModifyTableState *mtstate,
*/ */
static TupleTableSlot * static TupleTableSlot *
ExecDelete(ModifyTableState *mtstate, ExecDelete(ModifyTableState *mtstate,
ResultRelInfo *resultRelInfo,
ItemPointer tupleid, ItemPointer tupleid,
HeapTuple oldtuple, HeapTuple oldtuple,
TupleTableSlot *planSlot, TupleTableSlot *planSlot,
@ -718,8 +741,7 @@ ExecDelete(ModifyTableState *mtstate,
bool *tupleDeleted, bool *tupleDeleted,
TupleTableSlot **epqreturnslot) TupleTableSlot **epqreturnslot)
{ {
ResultRelInfo *resultRelInfo; Relation resultRelationDesc = resultRelInfo->ri_RelationDesc;
Relation resultRelationDesc;
TM_Result result; TM_Result result;
TM_FailureData tmfd; TM_FailureData tmfd;
TupleTableSlot *slot = NULL; TupleTableSlot *slot = NULL;
@ -728,12 +750,6 @@ ExecDelete(ModifyTableState *mtstate,
if (tupleDeleted) if (tupleDeleted)
*tupleDeleted = false; *tupleDeleted = false;
/*
* get information on the (current) result relation
*/
resultRelInfo = estate->es_result_relation_info;
resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW DELETE Triggers */ /* BEFORE ROW DELETE Triggers */
if (resultRelInfo->ri_TrigDesc && if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->trig_delete_before_row) resultRelInfo->ri_TrigDesc->trig_delete_before_row)
@ -1067,6 +1083,7 @@ ldelete:;
*/ */
static TupleTableSlot * static TupleTableSlot *
ExecUpdate(ModifyTableState *mtstate, ExecUpdate(ModifyTableState *mtstate,
ResultRelInfo *resultRelInfo,
ItemPointer tupleid, ItemPointer tupleid,
HeapTuple oldtuple, HeapTuple oldtuple,
TupleTableSlot *slot, TupleTableSlot *slot,
@ -1075,12 +1092,10 @@ ExecUpdate(ModifyTableState *mtstate,
EState *estate, EState *estate,
bool canSetTag) bool canSetTag)
{ {
ResultRelInfo *resultRelInfo; Relation resultRelationDesc = resultRelInfo->ri_RelationDesc;
Relation resultRelationDesc;
TM_Result result; TM_Result result;
TM_FailureData tmfd; TM_FailureData tmfd;
List *recheckIndexes = NIL; List *recheckIndexes = NIL;
TupleConversionMap *saved_tcs_map = NULL;
/* /*
* abort the operation if not running transactions * abort the operation if not running transactions
@ -1090,12 +1105,6 @@ ExecUpdate(ModifyTableState *mtstate,
ExecMaterializeSlot(slot); ExecMaterializeSlot(slot);
/*
* get information on the (current) result relation
*/
resultRelInfo = estate->es_result_relation_info;
resultRelationDesc = resultRelInfo->ri_RelationDesc;
/* BEFORE ROW UPDATE Triggers */ /* BEFORE ROW UPDATE Triggers */
if (resultRelInfo->ri_TrigDesc && if (resultRelInfo->ri_TrigDesc &&
resultRelInfo->ri_TrigDesc->trig_update_before_row) resultRelInfo->ri_TrigDesc->trig_update_before_row)
@ -1120,7 +1129,8 @@ ExecUpdate(ModifyTableState *mtstate,
*/ */
if (resultRelationDesc->rd_att->constr && if (resultRelationDesc->rd_att->constr &&
resultRelationDesc->rd_att->constr->has_generated_stored) resultRelationDesc->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, slot, CMD_UPDATE); ExecComputeStoredGenerated(resultRelInfo, estate, slot,
CMD_UPDATE);
/* /*
* update in foreign table: let the FDW do it * update in foreign table: let the FDW do it
@ -1157,7 +1167,8 @@ ExecUpdate(ModifyTableState *mtstate,
*/ */
if (resultRelationDesc->rd_att->constr && if (resultRelationDesc->rd_att->constr &&
resultRelationDesc->rd_att->constr->has_generated_stored) resultRelationDesc->rd_att->constr->has_generated_stored)
ExecComputeStoredGenerated(estate, slot, CMD_UPDATE); ExecComputeStoredGenerated(resultRelInfo, estate, slot,
CMD_UPDATE);
/* /*
* Check any RLS UPDATE WITH CHECK policies * Check any RLS UPDATE WITH CHECK policies
@ -1207,6 +1218,7 @@ lreplace:;
PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing; PartitionTupleRouting *proute = mtstate->mt_partition_tuple_routing;
int map_index; int map_index;
TupleConversionMap *tupconv_map; TupleConversionMap *tupconv_map;
TupleConversionMap *saved_tcs_map = NULL;
/* /*
* Disallow an INSERT ON CONFLICT DO UPDATE that causes the * Disallow an INSERT ON CONFLICT DO UPDATE that causes the
@ -1232,9 +1244,12 @@ lreplace:;
* Row movement, part 1. Delete the tuple, but skip RETURNING * Row movement, part 1. Delete the tuple, but skip RETURNING
* processing. We want to return rows from INSERT. * processing. We want to return rows from INSERT.
*/ */
ExecDelete(mtstate, tupleid, oldtuple, planSlot, epqstate, ExecDelete(mtstate, resultRelInfo, tupleid, oldtuple, planSlot,
estate, false, false /* canSetTag */ , epqstate, estate,
true /* changingPart */ , &tuple_deleted, &epqslot); false, /* processReturning */
false, /* canSetTag */
true, /* changingPart */
&tuple_deleted, &epqslot);
/* /*
* For some reason if DELETE didn't happen (e.g. trigger prevented * For some reason if DELETE didn't happen (e.g. trigger prevented
@ -1274,16 +1289,6 @@ lreplace:;
} }
} }
/*
* Updates set the transition capture map only when a new subplan
* is chosen. But for inserts, it is set for each row. So after
* INSERT, we need to revert back to the map created for UPDATE;
* otherwise the next UPDATE will incorrectly use the one created
* for INSERT. So first save the one created for UPDATE.
*/
if (mtstate->mt_transition_capture)
saved_tcs_map = mtstate->mt_transition_capture->tcs_map;
/* /*
* resultRelInfo is one of the per-subplan resultRelInfos. So we * resultRelInfo is one of the per-subplan resultRelInfos. So we
* should convert the tuple into root's tuple descriptor, since * should convert the tuple into root's tuple descriptor, since
@ -1301,18 +1306,18 @@ lreplace:;
mtstate->mt_root_tuple_slot); mtstate->mt_root_tuple_slot);
/* /*
* Prepare for tuple routing, making it look like we're inserting * ExecInsert() may scribble on mtstate->mt_transition_capture, so
* into the root. * save the currently active map.
*/ */
if (mtstate->mt_transition_capture)
saved_tcs_map = mtstate->mt_transition_capture->tcs_map;
/* Tuple routing starts from the root table. */
Assert(mtstate->rootResultRelInfo != NULL); Assert(mtstate->rootResultRelInfo != NULL);
slot = ExecPrepareTupleRouting(mtstate, estate, proute, ret_slot = ExecInsert(mtstate, mtstate->rootResultRelInfo, slot,
mtstate->rootResultRelInfo, slot); planSlot, estate, canSetTag);
ret_slot = ExecInsert(mtstate, slot, planSlot, /* Clear the INSERT's tuple and restore the saved map. */
estate, canSetTag);
/* Revert ExecPrepareTupleRouting's node change. */
estate->es_result_relation_info = resultRelInfo;
if (mtstate->mt_transition_capture) if (mtstate->mt_transition_capture)
{ {
mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL; mtstate->mt_transition_capture->tcs_original_insert_tuple = NULL;
@ -1476,7 +1481,9 @@ lreplace:;
/* insert index entries for tuple if necessary */ /* insert index entries for tuple if necessary */
if (resultRelInfo->ri_NumIndices > 0 && update_indexes) if (resultRelInfo->ri_NumIndices > 0 && update_indexes)
recheckIndexes = ExecInsertIndexTuples(slot, estate, false, NULL, NIL); recheckIndexes = ExecInsertIndexTuples(resultRelInfo,
slot, estate, false,
NULL, NIL);
} }
if (canSetTag) if (canSetTag)
@ -1715,7 +1722,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
*/ */
/* Execute UPDATE with projection */ /* Execute UPDATE with projection */
*returning = ExecUpdate(mtstate, conflictTid, NULL, *returning = ExecUpdate(mtstate, resultRelInfo, conflictTid, NULL,
resultRelInfo->ri_onConflict->oc_ProjSlot, resultRelInfo->ri_onConflict->oc_ProjSlot,
planSlot, planSlot,
&mtstate->mt_epqstate, mtstate->ps.state, &mtstate->mt_epqstate, mtstate->ps.state,
@ -1872,19 +1879,19 @@ ExecSetupTransitionCaptureState(ModifyTableState *mtstate, EState *estate)
* ExecPrepareTupleRouting --- prepare for routing one tuple * ExecPrepareTupleRouting --- prepare for routing one tuple
* *
* Determine the partition in which the tuple in slot is to be inserted, * Determine the partition in which the tuple in slot is to be inserted,
* and modify mtstate and estate to prepare for it. * and return its ResultRelInfo in *partRelInfo. The return value is
* a slot holding the tuple of the partition rowtype.
* *
* Caller must revert the estate changes after executing the insertion! * This also sets the transition table information in mtstate based on the
* In mtstate, transition capture changes may also need to be reverted. * selected partition.
*
* Returns a slot holding the tuple of the partition rowtype.
*/ */
static TupleTableSlot * static TupleTableSlot *
ExecPrepareTupleRouting(ModifyTableState *mtstate, ExecPrepareTupleRouting(ModifyTableState *mtstate,
EState *estate, EState *estate,
PartitionTupleRouting *proute, PartitionTupleRouting *proute,
ResultRelInfo *targetRelInfo, ResultRelInfo *targetRelInfo,
TupleTableSlot *slot) TupleTableSlot *slot,
ResultRelInfo **partRelInfo)
{ {
ResultRelInfo *partrel; ResultRelInfo *partrel;
PartitionRoutingInfo *partrouteinfo; PartitionRoutingInfo *partrouteinfo;
@ -1901,11 +1908,6 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
partrouteinfo = partrel->ri_PartitionInfo; partrouteinfo = partrel->ri_PartitionInfo;
Assert(partrouteinfo != NULL); Assert(partrouteinfo != NULL);
/*
* Make it look like we are inserting into the partition.
*/
estate->es_result_relation_info = partrel;
/* /*
* If we're capturing transition tuples, we might need to convert from the * If we're capturing transition tuples, we might need to convert from the
* partition rowtype to root partitioned table's rowtype. * partition rowtype to root partitioned table's rowtype.
@ -1950,6 +1952,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
slot = execute_attr_map_slot(map->attrMap, slot, new_slot); slot = execute_attr_map_slot(map->attrMap, slot, new_slot);
} }
*partRelInfo = partrel;
return slot; return slot;
} }
@ -2016,10 +2019,8 @@ static TupleTableSlot *
ExecModifyTable(PlanState *pstate) ExecModifyTable(PlanState *pstate)
{ {
ModifyTableState *node = castNode(ModifyTableState, pstate); ModifyTableState *node = castNode(ModifyTableState, pstate);
PartitionTupleRouting *proute = node->mt_partition_tuple_routing;
EState *estate = node->ps.state; EState *estate = node->ps.state;
CmdType operation = node->operation; CmdType operation = node->operation;
ResultRelInfo *saved_resultRelInfo;
ResultRelInfo *resultRelInfo; ResultRelInfo *resultRelInfo;
PlanState *subplanstate; PlanState *subplanstate;
JunkFilter *junkfilter; JunkFilter *junkfilter;
@ -2067,17 +2068,6 @@ ExecModifyTable(PlanState *pstate)
subplanstate = node->mt_plans[node->mt_whichplan]; subplanstate = node->mt_plans[node->mt_whichplan];
junkfilter = resultRelInfo->ri_junkFilter; junkfilter = resultRelInfo->ri_junkFilter;
/*
* es_result_relation_info must point to the currently active result
* relation while we are within this ModifyTable node. Even though
* ModifyTable nodes can't be nested statically, they can be nested
* dynamically (since our subplan could include a reference to a modifying
* CTE). So we have to save and restore the caller's value.
*/
saved_resultRelInfo = estate->es_result_relation_info;
estate->es_result_relation_info = resultRelInfo;
/* /*
* Fetch rows from subplan(s), and execute the required table modification * Fetch rows from subplan(s), and execute the required table modification
* for each row. * for each row.
@ -2111,7 +2101,6 @@ ExecModifyTable(PlanState *pstate)
resultRelInfo++; resultRelInfo++;
subplanstate = node->mt_plans[node->mt_whichplan]; subplanstate = node->mt_plans[node->mt_whichplan];
junkfilter = resultRelInfo->ri_junkFilter; junkfilter = resultRelInfo->ri_junkFilter;
estate->es_result_relation_info = resultRelInfo;
EvalPlanQualSetPlan(&node->mt_epqstate, subplanstate->plan, EvalPlanQualSetPlan(&node->mt_epqstate, subplanstate->plan,
node->mt_arowmarks[node->mt_whichplan]); node->mt_arowmarks[node->mt_whichplan]);
/* Prepare to convert transition tuples from this child. */ /* Prepare to convert transition tuples from this child. */
@ -2156,7 +2145,6 @@ ExecModifyTable(PlanState *pstate)
*/ */
slot = ExecProcessReturning(resultRelInfo, NULL, planSlot); slot = ExecProcessReturning(resultRelInfo, NULL, planSlot);
estate->es_result_relation_info = saved_resultRelInfo;
return slot; return slot;
} }
@ -2239,25 +2227,21 @@ ExecModifyTable(PlanState *pstate)
switch (operation) switch (operation)
{ {
case CMD_INSERT: case CMD_INSERT:
/* Prepare for tuple routing if needed. */ slot = ExecInsert(node, resultRelInfo, slot, planSlot,
if (proute)
slot = ExecPrepareTupleRouting(node, estate, proute,
resultRelInfo, slot);
slot = ExecInsert(node, slot, planSlot,
estate, node->canSetTag); estate, node->canSetTag);
/* Revert ExecPrepareTupleRouting's state change. */
if (proute)
estate->es_result_relation_info = resultRelInfo;
break; break;
case CMD_UPDATE: case CMD_UPDATE:
slot = ExecUpdate(node, tupleid, oldtuple, slot, planSlot, slot = ExecUpdate(node, resultRelInfo, tupleid, oldtuple, slot,
&node->mt_epqstate, estate, node->canSetTag); planSlot, &node->mt_epqstate, estate,
node->canSetTag);
break; break;
case CMD_DELETE: case CMD_DELETE:
slot = ExecDelete(node, tupleid, oldtuple, planSlot, slot = ExecDelete(node, resultRelInfo, tupleid, oldtuple,
&node->mt_epqstate, estate, planSlot, &node->mt_epqstate, estate,
true, node->canSetTag, true, /* processReturning */
false /* changingPart */ , NULL, NULL); node->canSetTag,
false, /* changingPart */
NULL, NULL);
break; break;
default: default:
elog(ERROR, "unknown operation"); elog(ERROR, "unknown operation");
@ -2269,15 +2253,9 @@ ExecModifyTable(PlanState *pstate)
* the work on next call. * the work on next call.
*/ */
if (slot) if (slot)
{
estate->es_result_relation_info = saved_resultRelInfo;
return slot; return slot;
}
} }
/* Restore es_result_relation_info before exiting */
estate->es_result_relation_info = saved_resultRelInfo;
/* /*
* We're done, but fire AFTER STATEMENT triggers before exiting. * We're done, but fire AFTER STATEMENT triggers before exiting.
*/ */
@ -2298,7 +2276,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
ModifyTableState *mtstate; ModifyTableState *mtstate;
CmdType operation = node->operation; CmdType operation = node->operation;
int nplans = list_length(node->plans); int nplans = list_length(node->plans);
ResultRelInfo *saved_resultRelInfo;
ResultRelInfo *resultRelInfo; ResultRelInfo *resultRelInfo;
Plan *subplan; Plan *subplan;
ListCell *l, ListCell *l,
@ -2346,14 +2323,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* call ExecInitNode on each of the plans to be executed and save the * call ExecInitNode on each of the plans to be executed and save the
* results into the array "mt_plans". This is also a convenient place to * results into the array "mt_plans". This is also a convenient place to
* verify that the proposed target relations are valid and open their * verify that the proposed target relations are valid and open their
* indexes for insertion of new index entries. Note we *must* set * indexes for insertion of new index entries.
* estate->es_result_relation_info correctly while we initialize each
* sub-plan; external modules such as FDWs may depend on that (see
* contrib/postgres_fdw/postgres_fdw.c: postgresBeginDirectModify() as one
* example).
*/ */
saved_resultRelInfo = estate->es_result_relation_info;
resultRelInfo = mtstate->resultRelInfo; resultRelInfo = mtstate->resultRelInfo;
i = 0; i = 0;
forboth(l, node->resultRelations, l1, node->plans) forboth(l, node->resultRelations, l1, node->plans)
@ -2400,7 +2371,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
update_tuple_routing_needed = true; update_tuple_routing_needed = true;
/* Now init the plan for this result rel */ /* Now init the plan for this result rel */
estate->es_result_relation_info = resultRelInfo;
mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags); mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
mtstate->mt_scans[i] = mtstate->mt_scans[i] =
ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]), ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]),
@ -2424,8 +2394,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
i++; i++;
} }
estate->es_result_relation_info = saved_resultRelInfo;
/* Get the target relation */ /* Get the target relation */
rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc; rel = (getTargetResultRelInfo(mtstate))->ri_RelationDesc;

View File

@ -1174,7 +1174,6 @@ apply_handle_insert(StringInfo s)
&TTSOpsVirtual); &TTSOpsVirtual);
resultRelInfo = makeNode(ResultRelInfo); resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0);
estate->es_result_relation_info = resultRelInfo;
/* Input functions may need an active snapshot, so get one */ /* Input functions may need an active snapshot, so get one */
PushActiveSnapshot(GetTransactionSnapshot()); PushActiveSnapshot(GetTransactionSnapshot());
@ -1214,7 +1213,7 @@ apply_handle_insert_internal(ResultRelInfo *relinfo,
ExecOpenIndices(relinfo, false); ExecOpenIndices(relinfo, false);
/* Do the insert. */ /* Do the insert. */
ExecSimpleRelationInsert(estate, remoteslot); ExecSimpleRelationInsert(relinfo, estate, remoteslot);
/* Cleanup. */ /* Cleanup. */
ExecCloseIndices(relinfo); ExecCloseIndices(relinfo);
@ -1300,7 +1299,6 @@ apply_handle_update(StringInfo s)
&TTSOpsVirtual); &TTSOpsVirtual);
resultRelInfo = makeNode(ResultRelInfo); resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0);
estate->es_result_relation_info = resultRelInfo;
/* /*
* Populate updatedCols so that per-column triggers can fire. This could * Populate updatedCols so that per-column triggers can fire. This could
@ -1392,7 +1390,8 @@ apply_handle_update_internal(ResultRelInfo *relinfo,
EvalPlanQualSetSlot(&epqstate, remoteslot); EvalPlanQualSetSlot(&epqstate, remoteslot);
/* Do the actual update. */ /* Do the actual update. */
ExecSimpleRelationUpdate(estate, &epqstate, localslot, remoteslot); ExecSimpleRelationUpdate(relinfo, estate, &epqstate, localslot,
remoteslot);
} }
else else
{ {
@ -1455,7 +1454,6 @@ apply_handle_delete(StringInfo s)
&TTSOpsVirtual); &TTSOpsVirtual);
resultRelInfo = makeNode(ResultRelInfo); resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0); InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0);
estate->es_result_relation_info = resultRelInfo;
PushActiveSnapshot(GetTransactionSnapshot()); PushActiveSnapshot(GetTransactionSnapshot());
@ -1508,7 +1506,7 @@ apply_handle_delete_internal(ResultRelInfo *relinfo, EState *estate,
EvalPlanQualSetSlot(&epqstate, localslot); EvalPlanQualSetSlot(&epqstate, localslot);
/* Do the actual delete. */ /* Do the actual delete. */
ExecSimpleRelationDelete(estate, &epqstate, localslot); ExecSimpleRelationDelete(relinfo, estate, &epqstate, localslot);
} }
else else
{ {
@ -1616,7 +1614,6 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo,
} }
MemoryContextSwitchTo(oldctx); MemoryContextSwitchTo(oldctx);
estate->es_result_relation_info = partrelinfo;
switch (operation) switch (operation)
{ {
case CMD_INSERT: case CMD_INSERT:
@ -1697,8 +1694,8 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo,
ExecOpenIndices(partrelinfo, false); ExecOpenIndices(partrelinfo, false);
EvalPlanQualSetSlot(&epqstate, remoteslot_part); EvalPlanQualSetSlot(&epqstate, remoteslot_part);
ExecSimpleRelationUpdate(estate, &epqstate, localslot, ExecSimpleRelationUpdate(partrelinfo, estate, &epqstate,
remoteslot_part); localslot, remoteslot_part);
ExecCloseIndices(partrelinfo); ExecCloseIndices(partrelinfo);
EvalPlanQualEnd(&epqstate); EvalPlanQualEnd(&epqstate);
} }
@ -1739,7 +1736,6 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo,
Assert(partrelinfo_new != partrelinfo); Assert(partrelinfo_new != partrelinfo);
/* DELETE old tuple found in the old partition. */ /* DELETE old tuple found in the old partition. */
estate->es_result_relation_info = partrelinfo;
apply_handle_delete_internal(partrelinfo, estate, apply_handle_delete_internal(partrelinfo, estate,
localslot, localslot,
&relmapentry->remoterel); &relmapentry->remoterel);
@ -1771,7 +1767,6 @@ apply_handle_tuple_routing(ResultRelInfo *relinfo,
slot_getallattrs(remoteslot); slot_getallattrs(remoteslot);
} }
MemoryContextSwitchTo(oldctx); MemoryContextSwitchTo(oldctx);
estate->es_result_relation_info = partrelinfo_new;
apply_handle_insert_internal(partrelinfo_new, estate, apply_handle_insert_internal(partrelinfo_new, estate,
remoteslot_part); remoteslot_part);
} }

View File

@ -576,10 +576,14 @@ extern TupleTableSlot *ExecGetReturningSlot(EState *estate, ResultRelInfo *relIn
*/ */
extern void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative); extern void ExecOpenIndices(ResultRelInfo *resultRelInfo, bool speculative);
extern void ExecCloseIndices(ResultRelInfo *resultRelInfo); extern void ExecCloseIndices(ResultRelInfo *resultRelInfo);
extern List *ExecInsertIndexTuples(TupleTableSlot *slot, EState *estate, bool noDupErr, extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate,
bool noDupErr,
bool *specConflict, List *arbiterIndexes); bool *specConflict, List *arbiterIndexes);
extern bool ExecCheckIndexConstraints(TupleTableSlot *slot, EState *estate, extern bool ExecCheckIndexConstraints(ResultRelInfo *resultRelInfo,
ItemPointer conflictTid, List *arbiterIndexes); TupleTableSlot *slot,
EState *estate, ItemPointer conflictTid,
List *arbiterIndexes);
extern void check_exclusion_constraint(Relation heap, Relation index, extern void check_exclusion_constraint(Relation heap, Relation index,
IndexInfo *indexInfo, IndexInfo *indexInfo,
ItemPointer tupleid, ItemPointer tupleid,
@ -596,10 +600,13 @@ extern bool RelationFindReplTupleByIndex(Relation rel, Oid idxoid,
extern bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, extern bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
TupleTableSlot *searchslot, TupleTableSlot *outslot); TupleTableSlot *searchslot, TupleTableSlot *outslot);
extern void ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot); extern void ExecSimpleRelationInsert(ResultRelInfo *resultRelInfo,
extern void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, EState *estate, TupleTableSlot *slot);
extern void ExecSimpleRelationUpdate(ResultRelInfo *resultRelInfo,
EState *estate, EPQState *epqstate,
TupleTableSlot *searchslot, TupleTableSlot *slot); TupleTableSlot *searchslot, TupleTableSlot *slot);
extern void ExecSimpleRelationDelete(EState *estate, EPQState *epqstate, extern void ExecSimpleRelationDelete(ResultRelInfo *resultRelInfo,
EState *estate, EPQState *epqstate,
TupleTableSlot *searchslot); TupleTableSlot *searchslot);
extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd); extern void CheckCmdReplicaIdentity(Relation rel, CmdType cmd);

View File

@ -15,7 +15,9 @@
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
extern void ExecComputeStoredGenerated(EState *estate, TupleTableSlot *slot, CmdType cmdtype); extern void ExecComputeStoredGenerated(ResultRelInfo *resultRelInfo,
EState *estate, TupleTableSlot *slot,
CmdType cmdtype);
extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags); extern ModifyTableState *ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags);
extern void ExecEndModifyTable(ModifyTableState *node); extern void ExecEndModifyTable(ModifyTableState *node);

View File

@ -525,7 +525,6 @@ typedef struct EState
List *es_opened_result_relations; /* List of non-NULL entries in List *es_opened_result_relations; /* List of non-NULL entries in
* es_result_relations in no * es_result_relations in no
* specific order */ * specific order */
ResultRelInfo *es_result_relation_info; /* currently active array elt */
PartitionDirectory es_partition_directory; /* for PartitionDesc lookup */ PartitionDirectory es_partition_directory; /* for PartitionDesc lookup */

View File

@ -818,9 +818,7 @@ drop role regress_coldesc_role;
drop table inserttest3; drop table inserttest3;
drop table brtrigpartcon; drop table brtrigpartcon;
drop function brtrigpartcon1trigf(); drop function brtrigpartcon1trigf();
-- check that "do nothing" BR triggers work with tuple-routing (this checks -- check that "do nothing" BR triggers work with tuple-routing
-- that estate->es_result_relation_info is appropriately set/reset for each
-- routed tuple)
create table donothingbrtrig_test (a int, b text) partition by list (a); create table donothingbrtrig_test (a int, b text) partition by list (a);
create table donothingbrtrig_test1 (b text, a int); create table donothingbrtrig_test1 (b text, a int);
create table donothingbrtrig_test2 (c text, b text, a int); create table donothingbrtrig_test2 (c text, b text, a int);

View File

@ -542,9 +542,7 @@ drop table inserttest3;
drop table brtrigpartcon; drop table brtrigpartcon;
drop function brtrigpartcon1trigf(); drop function brtrigpartcon1trigf();
-- check that "do nothing" BR triggers work with tuple-routing (this checks -- check that "do nothing" BR triggers work with tuple-routing
-- that estate->es_result_relation_info is appropriately set/reset for each
-- routed tuple)
create table donothingbrtrig_test (a int, b text) partition by list (a); create table donothingbrtrig_test (a int, b text) partition by list (a);
create table donothingbrtrig_test1 (b text, a int); create table donothingbrtrig_test1 (b text, a int);
create table donothingbrtrig_test2 (c text, b text, a int); create table donothingbrtrig_test2 (c text, b text, a int);