@ -67,6 +67,7 @@ static void ExecBatchInsert(ModifyTableState *mtstate,
int numSlots ,
EState * estate ,
bool canSetTag ) ;
static void ExecPendingInserts ( EState * estate ) ;
static bool ExecOnConflictUpdate ( ModifyTableState * mtstate ,
ResultRelInfo * resultRelInfo ,
ItemPointer conflictTid ,
@ -645,6 +646,10 @@ ExecInsert(ModifyTableState *mtstate,
if ( resultRelInfo - > ri_TrigDesc & &
resultRelInfo - > ri_TrigDesc - > trig_insert_before_row )
{
/* Flush any pending inserts, so rows are visible to the triggers */
if ( estate - > es_insert_pending_result_relations ! = NIL )
ExecPendingInserts ( estate ) ;
if ( ! ExecBRInsertTriggers ( estate , resultRelInfo , slot ) )
return NULL ; /* "do nothing" */
}
@ -678,6 +683,8 @@ ExecInsert(ModifyTableState *mtstate,
*/
if ( resultRelInfo - > ri_BatchSize > 1 )
{
bool flushed = false ;
/*
* When we ' ve reached the desired batch size , perform the
* insertion .
@ -690,6 +697,7 @@ ExecInsert(ModifyTableState *mtstate,
resultRelInfo - > ri_NumSlots ,
estate , canSetTag ) ;
resultRelInfo - > ri_NumSlots = 0 ;
flushed = true ;
}
oldContext = MemoryContextSwitchTo ( estate - > es_query_cxt ) ;
@ -732,6 +740,24 @@ ExecInsert(ModifyTableState *mtstate,
ExecCopySlot ( resultRelInfo - > ri_PlanSlots [ resultRelInfo - > ri_NumSlots ] ,
planSlot ) ;
/*
* If these are the first tuples stored in the buffers , add the
* target rel to the es_insert_pending_result_relations list ,
* except in the case where flushing was done above , in which case
* the target rel would already have been added to the list , so no
* need to do this .
*/
if ( resultRelInfo - > ri_NumSlots = = 0 & & ! flushed )
{
Assert ( ! list_member_ptr ( estate - > es_insert_pending_result_relations ,
resultRelInfo ) ) ;
estate - > es_insert_pending_result_relations =
lappend ( estate - > es_insert_pending_result_relations ,
resultRelInfo ) ;
}
Assert ( list_member_ptr ( estate - > es_insert_pending_result_relations ,
resultRelInfo ) ) ;
resultRelInfo - > ri_NumSlots + + ;
MemoryContextSwitchTo ( oldContext ) ;
@ -1034,9 +1060,8 @@ ExecBatchInsert(ModifyTableState *mtstate,
slot = rslots [ i ] ;
/*
* AFTER ROW Triggers or RETURNING expressions might reference the
* tableoid column , so ( re - ) initialize tts_tableOid before evaluating
* them .
* AFTER ROW Triggers might reference the tableoid column , so
* ( re - ) initialize tts_tableOid before evaluating them .
*/
slot - > tts_tableOid = RelationGetRelid ( resultRelInfo - > ri_RelationDesc ) ;
@ -1107,6 +1132,10 @@ ExecDelete(ModifyTableState *mtstate,
{
bool dodelete ;
/* Flush any pending inserts, so rows are visible to the triggers */
if ( estate - > es_insert_pending_result_relations ! = NIL )
ExecPendingInserts ( estate ) ;
dodelete = ExecBRDeleteTriggers ( estate , epqstate , resultRelInfo ,
tupleid , oldtuple , epqreturnslot ) ;
@ -1410,6 +1439,32 @@ ldelete:;
return NULL ;
}
/*
* ExecPendingInserts - - flushes all pending inserts to the foreign tables
*/
static void
ExecPendingInserts ( EState * estate )
{
ListCell * lc ;
foreach ( lc , estate - > es_insert_pending_result_relations )
{
ResultRelInfo * resultRelInfo = ( ResultRelInfo * ) lfirst ( lc ) ;
ModifyTableState * mtstate = resultRelInfo - > ri_ModifyTableState ;
Assert ( mtstate ) ;
ExecBatchInsert ( mtstate , resultRelInfo ,
resultRelInfo - > ri_Slots ,
resultRelInfo - > ri_PlanSlots ,
resultRelInfo - > ri_NumSlots ,
estate , mtstate - > canSetTag ) ;
resultRelInfo - > ri_NumSlots = 0 ;
}
list_free ( estate - > es_insert_pending_result_relations ) ;
estate - > es_insert_pending_result_relations = NIL ;
}
/*
* ExecCrossPartitionUpdate - - - Move an updated tuple to another partition .
*
@ -1634,6 +1689,10 @@ ExecUpdate(ModifyTableState *mtstate,
if ( resultRelInfo - > ri_TrigDesc & &
resultRelInfo - > ri_TrigDesc - > trig_update_before_row )
{
/* Flush any pending inserts, so rows are visible to the triggers */
if ( estate - > es_insert_pending_result_relations ! = NIL )
ExecPendingInserts ( estate ) ;
if ( ! ExecBRUpdateTriggers ( estate , epqstate , resultRelInfo ,
tupleid , oldtuple , slot ) )
return NULL ; /* "do nothing" */
@ -2361,9 +2420,6 @@ ExecModifyTable(PlanState *pstate)
ItemPointerData tuple_ctid ;
HeapTupleData oldtupdata ;
HeapTuple oldtuple ;
PartitionTupleRouting * proute = node - > mt_partition_tuple_routing ;
List * relinfos = NIL ;
ListCell * lc ;
CHECK_FOR_INTERRUPTS ( ) ;
@ -2620,21 +2676,8 @@ ExecModifyTable(PlanState *pstate)
/*
* Insert remaining tuples for batch insert .
*/
if ( proute )
relinfos = estate - > es_tuple_routing_result_relations ;
else
relinfos = estate - > es_opened_result_relations ;
foreach ( lc , relinfos )
{
resultRelInfo = lfirst ( lc ) ;
if ( resultRelInfo - > ri_NumSlots > 0 )
ExecBatchInsert ( node , resultRelInfo ,
resultRelInfo - > ri_Slots ,
resultRelInfo - > ri_PlanSlots ,
resultRelInfo - > ri_NumSlots ,
estate , node - > canSetTag ) ;
}
if ( estate - > es_insert_pending_result_relations ! = NIL )
ExecPendingInserts ( estate ) ;
/*
* We ' re done , but fire AFTER STATEMENT triggers before exiting .
@ -3140,6 +3183,13 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
}
else
resultRelInfo - > ri_BatchSize = 1 ;
/*
* If doing batch insert , setup back - link so we can easily find the
* mtstate again .
*/
if ( resultRelInfo - > ri_BatchSize > 1 )
resultRelInfo - > ri_ModifyTableState = mtstate ;
}
/*