@ -90,6 +90,7 @@ static void AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
int event , bool row_trigger ,
HeapTuple oldtup , HeapTuple newtup ,
List * recheckIndexes , Bitmapset * modifiedCols ) ;
static void AfterTriggerEnlargeQueryState ( void ) ;
/*
@ -3203,9 +3204,7 @@ typedef struct AfterTriggersData
int maxtransdepth ; /* allocated len of above arrays */
} AfterTriggersData ;
typedef AfterTriggersData * AfterTriggers ;
static AfterTriggers afterTriggers ;
static AfterTriggersData afterTriggers ;
static void AfterTriggerExecute ( AfterTriggerEvent event ,
Relation rel , TriggerDesc * trigdesc ,
@ -3228,7 +3227,7 @@ GetCurrentFDWTuplestore()
{
Tuplestorestate * ret ;
ret = afterTriggers - > fdw_tuplestores [ afterTriggers - > query_depth ] ;
ret = afterTriggers . fdw_tuplestores [ afterTriggers . query_depth ] ;
if ( ret = = NULL )
{
MemoryContext oldcxt ;
@ -3255,7 +3254,7 @@ GetCurrentFDWTuplestore()
CurrentResourceOwner = saveResourceOwner ;
MemoryContextSwitchTo ( oldcxt ) ;
afterTriggers - > fdw_tuplestores [ afterTriggers - > query_depth ] = ret ;
afterTriggers . fdw_tuplestores [ afterTriggers . query_depth ] = ret ;
}
return ret ;
@ -3271,7 +3270,7 @@ static bool
afterTriggerCheckState ( AfterTriggerShared evtshared )
{
Oid tgoid = evtshared - > ats_tgoid ;
SetConstraintState state = afterTriggers - > state ;
SetConstraintState state = afterTriggers . state ;
int i ;
/*
@ -3282,19 +3281,22 @@ afterTriggerCheckState(AfterTriggerShared evtshared)
return false ;
/*
* Check if SET CONSTRAINTS has been executed for this specific trigger .
* If constraint state exists , SET CONSTRAINTS might have been executed
* either for this trigger or for all triggers .
*/
for ( i = 0 ; i < state - > numstates ; i + + )
if ( state ! = NULL )
{
if ( state - > trigstates [ i ] . sct_tgoid = = tgoid )
return state - > trigstates [ i ] . sct_tgisdeferred ;
}
/* Check for SET CONSTRAINTS for this specific trigger. */
for ( i = 0 ; i < state - > numstates ; i + + )
{
if ( state - > trigstates [ i ] . sct_tgoid = = tgoid )
return state - > trigstates [ i ] . sct_tgisdeferred ;
}
/*
* Check if SET CONSTRAINTS ALL has been executed ; if so use that .
*/
if ( state - > all_isset )
return state - > all_isdeferred ;
/* Check for SET CONSTRAINTS ALL. */
if ( state - > all_isset )
return state - > all_isdeferred ;
}
/*
* Otherwise return the default state for the trigger .
@ -3331,8 +3333,8 @@ afterTriggerAddEvent(AfterTriggerEventList *events,
Size chunksize ;
/* Create event context if we didn't already */
if ( afterTriggers - > event_cxt = = NULL )
afterTriggers - > event_cxt =
if ( afterTriggers . event_cxt = = NULL )
afterTriggers . event_cxt =
AllocSetContextCreate ( TopTransactionContext ,
" AfterTriggerEvents " ,
ALLOCSET_DEFAULT_MINSIZE ,
@ -3375,7 +3377,7 @@ afterTriggerAddEvent(AfterTriggerEventList *events,
chunksize / = 2 ; /* too many shared records */
chunksize = Min ( chunksize , MAX_CHUNK_SIZE ) ;
}
chunk = MemoryContextAlloc ( afterTriggers - > event_cxt , chunksize ) ;
chunk = MemoryContextAlloc ( afterTriggers . event_cxt , chunksize ) ;
chunk - > next = NULL ;
chunk - > freeptr = CHUNK_DATA_START ( chunk ) ;
chunk - > endptr = chunk - > endfree = ( char * ) chunk + chunksize ;
@ -3706,7 +3708,7 @@ afterTriggerMarkEvents(AfterTriggerEventList *events,
/*
* Mark it as to be fired in this firing cycle .
*/
evtshared - > ats_firing_id = afterTriggers - > firing_counter ;
evtshared - > ats_firing_id = afterTriggers . firing_counter ;
event - > ate_flags | = AFTER_TRIGGER_IN_PROGRESS ;
found = true ;
}
@ -3898,40 +3900,28 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
void
AfterTriggerBeginXact ( void )
{
Assert ( afterTriggers = = NULL ) ;
/*
* Initialize after - trigger state structure to empty
*/
afterTriggers . firing_counter = ( CommandId ) 1 ; /* mustn't be 0 */
afterTriggers . query_depth = - 1 ;
/*
* Build empty after - trigger state structure
* Verify that there is no leftover state remaining . If these assertions
* trip , it means that AfterTriggerEndXact wasn ' t called or didn ' t clean
* up properly .
*/
afterTriggers = ( AfterTriggers )
MemoryContextAlloc ( TopTransactionContext ,
sizeof ( AfterTriggersData ) ) ;
afterTriggers - > firing_counter = ( CommandId ) 1 ; /* mustn't be 0 */
afterTriggers - > state = SetConstraintStateCreate ( 8 ) ;
afterTriggers - > events . head = NULL ;
afterTriggers - > events . tail = NULL ;
afterTriggers - > events . tailfree = NULL ;
afterTriggers - > query_depth = - 1 ;
/* We initialize the arrays to a reasonable size */
afterTriggers - > query_stack = ( AfterTriggerEventList * )
MemoryContextAlloc ( TopTransactionContext ,
8 * sizeof ( AfterTriggerEventList ) ) ;
afterTriggers - > fdw_tuplestores = ( Tuplestorestate * * )
MemoryContextAllocZero ( TopTransactionContext ,
8 * sizeof ( Tuplestorestate * ) ) ;
afterTriggers - > maxquerydepth = 8 ;
/* Context for events is created only when needed */
afterTriggers - > event_cxt = NULL ;
/* Subtransaction stack is empty until/unless needed */
afterTriggers - > state_stack = NULL ;
afterTriggers - > events_stack = NULL ;
afterTriggers - > depth_stack = NULL ;
afterTriggers - > firing_stack = NULL ;
afterTriggers - > maxtransdepth = 0 ;
Assert ( afterTriggers . state = = NULL ) ;
Assert ( afterTriggers . query_stack = = NULL ) ;
Assert ( afterTriggers . fdw_tuplestores = = NULL ) ;
Assert ( afterTriggers . maxquerydepth = = 0 ) ;
Assert ( afterTriggers . event_cxt = = NULL ) ;
Assert ( afterTriggers . events . head = = NULL ) ;
Assert ( afterTriggers . state_stack = = NULL ) ;
Assert ( afterTriggers . events_stack = = NULL ) ;
Assert ( afterTriggers . depth_stack = = NULL ) ;
Assert ( afterTriggers . firing_stack = = NULL ) ;
Assert ( afterTriggers . maxtransdepth = = 0 ) ;
}
@ -3939,48 +3929,15 @@ AfterTriggerBeginXact(void)
* AfterTriggerBeginQuery ( )
*
* Called just before we start processing a single query within a
* transaction ( or subtransaction ) . Set up to record AFTER trigger
* events queued by the query . Note that it is allowed to have
* nested queries within a ( sub ) transaction .
* transaction ( or subtransaction ) . Most of the real work gets deferred
* until somebody actually tries to queue a trigger event .
* - - - - - - - - - -
*/
void
AfterTriggerBeginQuery ( void )
{
AfterTriggerEventList * events ;
/* Must be inside a transaction */
Assert ( afterTriggers ! = NULL ) ;
/* Increase the query stack depth */
afterTriggers - > query_depth + + ;
/*
* Allocate more space in the query stack if needed .
*/
if ( afterTriggers - > query_depth > = afterTriggers - > maxquerydepth )
{
/* repalloc will keep the stack in the same context */
int old_alloc = afterTriggers - > maxquerydepth ;
int new_alloc = old_alloc * 2 ;
afterTriggers - > query_stack = ( AfterTriggerEventList * )
repalloc ( afterTriggers - > query_stack ,
new_alloc * sizeof ( AfterTriggerEventList ) ) ;
afterTriggers - > fdw_tuplestores = ( Tuplestorestate * * )
repalloc ( afterTriggers - > fdw_tuplestores ,
new_alloc * sizeof ( Tuplestorestate * ) ) ;
/* Clear newly-allocated slots for subsequent lazy initialization. */
memset ( afterTriggers - > fdw_tuplestores + old_alloc ,
0 , ( new_alloc - old_alloc ) * sizeof ( Tuplestorestate * ) ) ;
afterTriggers - > maxquerydepth = new_alloc ;
}
/* Initialize this query's list to empty */
events = & afterTriggers - > query_stack [ afterTriggers - > query_depth ] ;
events - > head = NULL ;
events - > tail = NULL ;
events - > tailfree = NULL ;
afterTriggers . query_depth + + ;
}
@ -4002,11 +3959,18 @@ AfterTriggerEndQuery(EState *estate)
AfterTriggerEventList * events ;
Tuplestorestate * fdw_tuplestore ;
/* Must be inside a transaction */
Assert ( afterTriggers ! = NULL ) ;
/* Must be inside a query, too */
Assert ( afterTriggers - > query_depth > = 0 ) ;
Assert ( afterTriggers . query_depth > = 0 ) ;
/*
* If we never even got as far as initializing the event stack , there
* certainly won ' t be any events , so exit quickly .
*/
if ( afterTriggers . query_depth > = afterTriggers . maxquerydepth )
{
afterTriggers . query_depth - - ;
return ;
}
/*
* Process all immediate - mode triggers queued by the query , and move the
@ -4032,10 +3996,10 @@ AfterTriggerEndQuery(EState *estate)
*/
for ( ; ; )
{
events = & afterTriggers - > query_stack [ afterTriggers - > query_depth ] ;
if ( afterTriggerMarkEvents ( events , & afterTriggers - > events , true ) )
events = & afterTriggers . query_stack [ afterTriggers . query_depth ] ;
if ( afterTriggerMarkEvents ( events , & afterTriggers . events , true ) )
{
CommandId firing_id = afterTriggers - > firing_counter + + ;
CommandId firing_id = afterTriggers . firing_counter + + ;
/* OK to delete the immediate events after processing them */
if ( afterTriggerInvokeEvents ( events , firing_id , estate , true ) )
@ -4046,15 +4010,15 @@ AfterTriggerEndQuery(EState *estate)
}
/* Release query-local storage for events, including tuplestore if any */
fdw_tuplestore = afterTriggers - > fdw_tuplestores [ afterTriggers - > query_depth ] ;
fdw_tuplestore = afterTriggers . fdw_tuplestores [ afterTriggers . query_depth ] ;
if ( fdw_tuplestore )
{
tuplestore_end ( fdw_tuplestore ) ;
afterTriggers - > fdw_tuplestores [ afterTriggers - > query_depth ] = NULL ;
afterTriggers . fdw_tuplestores [ afterTriggers . query_depth ] = NULL ;
}
afterTriggerFreeEventList ( & afterTriggers - > query_stack [ afterTriggers - > query_depth ] ) ;
afterTriggerFreeEventList ( & afterTriggers . query_stack [ afterTriggers . query_depth ] ) ;
afterTriggers - > query_depth - - ;
afterTriggers . query_depth - - ;
}
@ -4075,18 +4039,15 @@ AfterTriggerFireDeferred(void)
AfterTriggerEventList * events ;
bool snap_pushed = false ;
/* Must be inside a transaction */
Assert ( afterTriggers ! = NULL ) ;
/* ... but not inside a query */
Assert ( afterTriggers - > query_depth = = - 1 ) ;
/* Must not be inside a query */
Assert ( afterTriggers . query_depth = = - 1 ) ;
/*
* If there are any triggers to fire , make sure we have set a snapshot for
* them to use . ( Since PortalRunUtility doesn ' t set a snap for COMMIT , we
* can ' t assume ActiveSnapshot is valid on entry . )
*/
events = & afterTriggers - > events ;
events = & afterTriggers . events ;
if ( events - > head ! = NULL )
{
PushActiveSnapshot ( GetTransactionSnapshot ( ) ) ;
@ -4099,7 +4060,7 @@ AfterTriggerFireDeferred(void)
*/
while ( afterTriggerMarkEvents ( events , NULL , false ) )
{
CommandId firing_id = afterTriggers - > firing_counter + + ;
CommandId firing_id = afterTriggers . firing_counter + + ;
if ( afterTriggerInvokeEvents ( events , firing_id , NULL , true ) )
break ; /* all fired */
@ -4132,7 +4093,7 @@ void
AfterTriggerEndXact ( bool isCommit )
{
/*
* Forget everything we know about AFTER triggers .
* Forget the pending - events list .
*
* Since all the info is in TopTransactionContext or children thereof , we
* don ' t really need to do anything to reclaim memory . However , the
@ -4140,10 +4101,39 @@ AfterTriggerEndXact(bool isCommit)
* soon as possible - - - especially if we are aborting because we ran out
* of memory for the list !
*/
if ( afterTriggers & & afterTriggers - > event_cxt )
MemoryContextDelete ( afterTriggers - > event_cxt ) ;
if ( afterTriggers . event_cxt )
{
MemoryContextDelete ( afterTriggers . event_cxt ) ;
afterTriggers . event_cxt = NULL ;
afterTriggers . events . head = NULL ;
afterTriggers . events . tail = NULL ;
afterTriggers . events . tailfree = NULL ;
}
/*
* Forget any subtransaction state as well . Since this can ' t be very
* large , we let the eventual reset of TopTransactionContext free the
* memory instead of doing it here .
*/
afterTriggers . state_stack = NULL ;
afterTriggers . events_stack = NULL ;
afterTriggers . depth_stack = NULL ;
afterTriggers . firing_stack = NULL ;
afterTriggers . maxtransdepth = 0 ;
/*
* Forget the query stack and constrant - related state information . As
* with the subtransaction state information , we don ' t bother freeing the
* memory here .
*/
afterTriggers . query_stack = NULL ;
afterTriggers . fdw_tuplestores = NULL ;
afterTriggers . maxquerydepth = 0 ;
afterTriggers . state = NULL ;
afterTriggers = NULL ;
/* No more afterTriggers manipulation until next transaction starts. */
afterTriggers . query_depth = - 1 ;
}
/*
@ -4156,57 +4146,50 @@ AfterTriggerBeginSubXact(void)
{
int my_level = GetCurrentTransactionNestLevel ( ) ;
/*
* Ignore call if the transaction is in aborted state . ( Probably
* shouldn ' t happen ? )
*/
if ( afterTriggers = = NULL )
return ;
/*
* Allocate more space in the stacks if needed . ( Note : because the
* minimum nest level of a subtransaction is 2 , we waste the first couple
* entries of each array ; not worth the notational effort to avoid it . )
*/
while ( my_level > = afterTriggers - > maxtransdepth )
while ( my_level > = afterTriggers . maxtransdepth )
{
if ( afterTriggers - > maxtransdepth = = 0 )
if ( afterTriggers . maxtransdepth = = 0 )
{
MemoryContext old_cxt ;
old_cxt = MemoryContextSwitchTo ( TopTransactionContext ) ;
# define DEFTRIG_INITALLOC 8
afterTriggers - > state_stack = ( SetConstraintState * )
afterTriggers . state_stack = ( SetConstraintState * )
palloc ( DEFTRIG_INITALLOC * sizeof ( SetConstraintState ) ) ;
afterTriggers - > events_stack = ( AfterTriggerEventList * )
afterTriggers . events_stack = ( AfterTriggerEventList * )
palloc ( DEFTRIG_INITALLOC * sizeof ( AfterTriggerEventList ) ) ;
afterTriggers - > depth_stack = ( int * )
afterTriggers . depth_stack = ( int * )
palloc ( DEFTRIG_INITALLOC * sizeof ( int ) ) ;
afterTriggers - > firing_stack = ( CommandId * )
afterTriggers . firing_stack = ( CommandId * )
palloc ( DEFTRIG_INITALLOC * sizeof ( CommandId ) ) ;
afterTriggers - > maxtransdepth = DEFTRIG_INITALLOC ;
afterTriggers . maxtransdepth = DEFTRIG_INITALLOC ;
MemoryContextSwitchTo ( old_cxt ) ;
}
else
{
/* repalloc will keep the stacks in the same context */
int new_alloc = afterTriggers - > maxtransdepth * 2 ;
int new_alloc = afterTriggers . maxtransdepth * 2 ;
afterTriggers - > state_stack = ( SetConstraintState * )
repalloc ( afterTriggers - > state_stack ,
afterTriggers . state_stack = ( SetConstraintState * )
repalloc ( afterTriggers . state_stack ,
new_alloc * sizeof ( SetConstraintState ) ) ;
afterTriggers - > events_stack = ( AfterTriggerEventList * )
repalloc ( afterTriggers - > events_stack ,
afterTriggers . events_stack = ( AfterTriggerEventList * )
repalloc ( afterTriggers . events_stack ,
new_alloc * sizeof ( AfterTriggerEventList ) ) ;
afterTriggers - > depth_stack = ( int * )
repalloc ( afterTriggers - > depth_stack ,
afterTriggers . depth_stack = ( int * )
repalloc ( afterTriggers . depth_stack ,
new_alloc * sizeof ( int ) ) ;
afterTriggers - > firing_stack = ( CommandId * )
repalloc ( afterTriggers - > firing_stack ,
afterTriggers . firing_stack = ( CommandId * )
repalloc ( afterTriggers . firing_stack ,
new_alloc * sizeof ( CommandId ) ) ;
afterTriggers - > maxtransdepth = new_alloc ;
afterTriggers . maxtransdepth = new_alloc ;
}
}
@ -4215,10 +4198,10 @@ AfterTriggerBeginSubXact(void)
* is not saved until / unless changed . Likewise , we don ' t make a
* per - subtransaction event context until needed .
*/
afterTriggers - > state_stack [ my_level ] = NULL ;
afterTriggers - > events_stack [ my_level ] = afterTriggers - > events ;
afterTriggers - > depth_stack [ my_level ] = afterTriggers - > query_depth ;
afterTriggers - > firing_stack [ my_level ] = afterTriggers - > firing_counter ;
afterTriggers . state_stack [ my_level ] = NULL ;
afterTriggers . events_stack [ my_level ] = afterTriggers . events ;
afterTriggers . depth_stack [ my_level ] = afterTriggers . query_depth ;
afterTriggers . firing_stack [ my_level ] = afterTriggers . firing_counter ;
}
/*
@ -4235,27 +4218,20 @@ AfterTriggerEndSubXact(bool isCommit)
AfterTriggerEventChunk * chunk ;
CommandId subxact_firing_id ;
/*
* Ignore call if the transaction is in aborted state . ( Probably
* unneeded )
*/
if ( afterTriggers = = NULL )
return ;
/*
* Pop the prior state if needed .
*/
if ( isCommit )
{
Assert ( my_level < afterTriggers - > maxtransdepth ) ;
Assert ( my_level < afterTriggers . maxtransdepth ) ;
/* If we saved a prior state, we don't need it anymore */
state = afterTriggers - > state_stack [ my_level ] ;
state = afterTriggers . state_stack [ my_level ] ;
if ( state ! = NULL )
pfree ( state ) ;
/* this avoids double pfree if error later: */
afterTriggers - > state_stack [ my_level ] = NULL ;
Assert ( afterTriggers - > query_depth = =
afterTriggers - > depth_stack [ my_level ] ) ;
afterTriggers . state_stack [ my_level ] = NULL ;
Assert ( afterTriggers . query_depth = =
afterTriggers . depth_stack [ my_level ] ) ;
}
else
{
@ -4264,7 +4240,7 @@ AfterTriggerEndSubXact(bool isCommit)
* AfterTriggerBeginSubXact , in which case we mustn ' t risk touching
* stack levels that aren ' t there .
*/
if ( my_level > = afterTriggers - > maxtransdepth )
if ( my_level > = afterTriggers . maxtransdepth )
return ;
/*
@ -4273,42 +4249,46 @@ AfterTriggerEndSubXact(bool isCommit)
* subtransaction will not add events to query levels started in a
* earlier transaction state .
*/
while ( afterTriggers - > query_depth > afterTriggers - > depth_stack [ my_level ] )
while ( afterTriggers . query_depth > afterTriggers . depth_stack [ my_level ] )
{
Tuplestorestate * ts ;
ts = afterTriggers - > fdw_tuplestores [ afterTriggers - > query_depth ] ;
if ( ts )
if ( afterTriggers . query_depth < afterTriggers . maxquerydepth )
{
tuplestore_end ( ts ) ;
afterTriggers - > fdw_tuplestores [ afterTriggers - > query_depth ] = NULL ;
Tuplestorestate * ts ;
ts = afterTriggers . fdw_tuplestores [ afterTriggers . query_depth ] ;
if ( ts )
{
tuplestore_end ( ts ) ;
afterTriggers . fdw_tuplestores [ afterTriggers . query_depth ] = NULL ;
}
afterTriggerFreeEventList ( & afterTriggers . query_stack [ afterTriggers . query_depth ] ) ;
}
afterTriggerFreeEventList ( & afterTriggers - > query_stack [ afterTriggers - > query_depth ] ) ;
afterTriggers - > query_depth - - ;
afterTriggers . query_depth - - ;
}
Assert ( afterTriggers - > query_depth = =
afterTriggers - > depth_stack [ my_level ] ) ;
Assert ( afterTriggers . query_depth = =
afterTriggers . depth_stack [ my_level ] ) ;
/*
* Restore the global deferred - event list to its former length ,
* discarding any events queued by the subxact .
*/
afterTriggerRestoreEventList ( & afterTriggers - > events ,
& afterTriggers - > events_stack [ my_level ] ) ;
afterTriggerRestoreEventList ( & afterTriggers . events ,
& afterTriggers . events_stack [ my_level ] ) ;
/*
* Restore the trigger state . If the saved state is NULL , then this
* subxact didn ' t save it , so it doesn ' t need restoring .
*/
state = afterTriggers - > state_stack [ my_level ] ;
state = afterTriggers . state_stack [ my_level ] ;
if ( state ! = NULL )
{
pfree ( afterTriggers - > state ) ;
afterTriggers - > state = state ;
pfree ( afterTriggers . state ) ;
afterTriggers . state = state ;
}
/* this avoids double pfree if error later: */
afterTriggers - > state_stack [ my_level ] = NULL ;
afterTriggers . state_stack [ my_level ] = NULL ;
/*
* Scan for any remaining deferred events that were marked DONE or IN
@ -4318,8 +4298,8 @@ AfterTriggerEndSubXact(bool isCommit)
* ( This essentially assumes that the current subxact includes all
* subxacts started after it . )
*/
subxact_firing_id = afterTriggers - > firing_stack [ my_level ] ;
for_each_event_chunk ( event , chunk , afterTriggers - > events )
subxact_firing_id = afterTriggers . firing_stack [ my_level ] ;
for_each_event_chunk ( event , chunk , afterTriggers . events )
{
AfterTriggerShared evtshared = GetTriggerSharedData ( event ) ;
@ -4334,6 +4314,66 @@ AfterTriggerEndSubXact(bool isCommit)
}
}
/* ----------
* AfterTriggerEnlargeQueryState ( )
*
* Prepare the necessary state so that we can record AFTER trigger events
* queued by a query . It is allowed to have nested queries within a
* ( sub ) transaction , so we need to have separate state for each query
* nesting level .
* - - - - - - - - - -
*/
static void
AfterTriggerEnlargeQueryState ( void )
{
int init_depth = afterTriggers . maxquerydepth ;
Assert ( afterTriggers . query_depth > = afterTriggers . maxquerydepth ) ;
if ( afterTriggers . maxquerydepth = = 0 )
{
int new_alloc = Max ( afterTriggers . query_depth , 8 ) ;
afterTriggers . query_stack = ( AfterTriggerEventList * )
MemoryContextAlloc ( TopTransactionContext ,
new_alloc * sizeof ( AfterTriggerEventList ) ) ;
afterTriggers . fdw_tuplestores = ( Tuplestorestate * * )
MemoryContextAllocZero ( TopTransactionContext ,
new_alloc * sizeof ( Tuplestorestate * ) ) ;
afterTriggers . maxquerydepth = new_alloc ;
}
else
{
/* repalloc will keep the stack in the same context */
int old_alloc = afterTriggers . maxquerydepth ;
int new_alloc = Max ( afterTriggers . query_depth , old_alloc * 2 ) ;
afterTriggers . query_stack = ( AfterTriggerEventList * )
repalloc ( afterTriggers . query_stack ,
new_alloc * sizeof ( AfterTriggerEventList ) ) ;
afterTriggers . fdw_tuplestores = ( Tuplestorestate * * )
repalloc ( afterTriggers . fdw_tuplestores ,
new_alloc * sizeof ( Tuplestorestate * ) ) ;
/* Clear newly-allocated slots for subsequent lazy initialization. */
memset ( afterTriggers . fdw_tuplestores + old_alloc ,
0 , ( new_alloc - old_alloc ) * sizeof ( Tuplestorestate * ) ) ;
afterTriggers . maxquerydepth = new_alloc ;
}
/* Initialize new query lists to empty */
while ( init_depth < afterTriggers . maxquerydepth )
{
AfterTriggerEventList * events ;
events = & afterTriggers . query_stack [ init_depth ] ;
events - > head = NULL ;
events - > tail = NULL ;
events - > tailfree = NULL ;
+ + init_depth ;
}
}
/*
* Create an empty SetConstraintState with room for numalloc trigstates
*/
@ -4417,21 +4457,19 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
{
int my_level = GetCurrentTransactionNestLevel ( ) ;
/*
* Ignore call if we aren ' t in a transaction . ( Shouldn ' t happen ? )
*/
if ( afterTriggers = = NULL )
return ;
/* If we haven't already done so, initialize our state. */
if ( afterTriggers . state = = NULL )
afterTriggers . state = SetConstraintStateCreate ( 8 ) ;
/*
* If in a subtransaction , and we didn ' t save the current state already ,
* save it so it can be restored if the subtransaction aborts .
*/
if ( my_level > 1 & &
afterTriggers - > state_stack [ my_level ] = = NULL )
afterTriggers . state_stack [ my_level ] = = NULL )
{
afterTriggers - > state_stack [ my_level ] =
SetConstraintStateCopy ( afterTriggers - > state ) ;
afterTriggers . state_stack [ my_level ] =
SetConstraintStateCopy ( afterTriggers . state ) ;
}
/*
@ -4442,13 +4480,13 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
/*
* Forget any previous SET CONSTRAINTS commands in this transaction .
*/
afterTriggers - > state - > numstates = 0 ;
afterTriggers . state - > numstates = 0 ;
/*
* Set the per - transaction ALL state to known .
*/
afterTriggers - > state - > all_isset = true ;
afterTriggers - > state - > all_isdeferred = stmt - > deferred ;
afterTriggers . state - > all_isset = true ;
afterTriggers . state - > all_isdeferred = stmt - > deferred ;
}
else
{
@ -4622,7 +4660,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
foreach ( lc , tgoidlist )
{
Oid tgoid = lfirst_oid ( lc ) ;
SetConstraintState state = afterTriggers - > state ;
SetConstraintState state = afterTriggers . state ;
bool found = false ;
int i ;
@ -4637,7 +4675,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
}
if ( ! found )
{
afterTriggers - > state =
afterTriggers . state =
SetConstraintStateAddItem ( state , tgoid , stmt - > deferred ) ;
}
}
@ -4656,12 +4694,12 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
*/
if ( ! stmt - > deferred )
{
AfterTriggerEventList * events = & afterTriggers - > events ;
AfterTriggerEventList * events = & afterTriggers . events ;
bool snapshot_set = false ;
while ( afterTriggerMarkEvents ( events , NULL , true ) )
{
CommandId firing_id = afterTriggers - > firing_counter + + ;
CommandId firing_id = afterTriggers . firing_counter + + ;
/*
* Make sure a snapshot has been established in case trigger
@ -4715,12 +4753,8 @@ AfterTriggerPendingOnRel(Oid relid)
AfterTriggerEventChunk * chunk ;
int depth ;
/* No-op if we aren't in a transaction. (Shouldn't happen?) */
if ( afterTriggers = = NULL )
return false ;
/* Scan queued events */
for_each_event_chunk ( event , chunk , afterTriggers - > events )
for_each_event_chunk ( event , chunk , afterTriggers . events )
{
AfterTriggerShared evtshared = GetTriggerSharedData ( event ) ;
@ -4741,9 +4775,9 @@ AfterTriggerPendingOnRel(Oid relid)
* if TRUNCATE / etc is executed by a function or trigger within an updating
* query on the same relation , which is pretty perverse , but let ' s check .
*/
for ( depth = 0 ; depth < = afterTriggers - > query_depth ; depth + + )
for ( depth = 0 ; depth < = afterTriggers . query_depth ; depth + + )
{
for_each_event_chunk ( event , chunk , afterTriggers - > query_stack [ depth ] )
for_each_event_chunk ( event , chunk , afterTriggers . query_stack [ depth ] )
{
AfterTriggerShared evtshared = GetTriggerSharedData ( event ) ;
@ -4787,15 +4821,17 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
Tuplestorestate * fdw_tuplestore = NULL ;
/*
* Check state . We use normal tests not Asserts because it is possible to
* Check state . We use a normal test not Assert because it is possible to
* reach here in the wrong state given misconfigured RI triggers , in
* particular deferring a cascade action trigger .
*/
if ( afterTriggers = = NULL )
elog ( ERROR , " AfterTriggerSaveEvent() called outside of transaction " ) ;
if ( afterTriggers - > query_depth < 0 )
if ( afterTriggers . query_depth < 0 )
elog ( ERROR , " AfterTriggerSaveEvent() called outside of query " ) ;
/* Be sure we have enough space to record events at this query depth. */
if ( afterTriggers . query_depth > = afterTriggers . maxquerydepth )
AfterTriggerEnlargeQueryState ( ) ;
/*
* Validate the event code and collect the associated tuple CTIDs .
*
@ -4959,7 +4995,7 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
new_shared . ats_relid = RelationGetRelid ( rel ) ;
new_shared . ats_firing_id = 0 ;
afterTriggerAddEvent ( & afterTriggers - > query_stack [ afterTriggers - > query_depth ] ,
afterTriggerAddEvent ( & afterTriggers . query_stack [ afterTriggers . query_depth ] ,
& new_event , & new_shared ) ;
}