7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
9
* IDENTIFICATION
10
- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.82 2000/12/18 00:44:46 tgl Exp $
10
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.83 2001/01/22 00:50:07 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -36,7 +36,8 @@ static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
36
36
static HeapTuple GetTupleForTrigger (EState * estate , ItemPointer tid ,
37
37
TupleTableSlot * * newSlot );
38
38
static HeapTuple ExecCallTriggerFunc (Trigger * trigger ,
39
- TriggerData * trigdata );
39
+ TriggerData * trigdata ,
40
+ MemoryContext per_tuple_context );
40
41
static void DeferredTriggerSaveEvent (Relation rel , int event ,
41
42
HeapTuple oldtup , HeapTuple newtup );
42
43
@@ -831,10 +832,13 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
831
832
}
832
833
833
834
static HeapTuple
834
- ExecCallTriggerFunc (Trigger * trigger , TriggerData * trigdata )
835
+ ExecCallTriggerFunc (Trigger * trigger ,
836
+ TriggerData * trigdata ,
837
+ MemoryContext per_tuple_context )
835
838
{
836
839
FunctionCallInfoData fcinfo ;
837
840
Datum result ;
841
+ MemoryContext oldContext ;
838
842
839
843
/*
840
844
* Fmgr lookup info is cached in the Trigger structure,
@@ -843,6 +847,14 @@ ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
843
847
if (trigger -> tgfunc .fn_oid == InvalidOid )
844
848
fmgr_info (trigger -> tgfoid , & trigger -> tgfunc );
845
849
850
+ /*
851
+ * Do the function evaluation in the per-tuple memory context,
852
+ * so that leaked memory will be reclaimed once per tuple.
853
+ * Note in particular that any new tuple created by the trigger function
854
+ * will live till the end of the tuple cycle.
855
+ */
856
+ oldContext = MemoryContextSwitchTo (per_tuple_context );
857
+
846
858
/*
847
859
* Call the function, passing no arguments but setting a context.
848
860
*/
@@ -853,6 +865,8 @@ ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
853
865
854
866
result = FunctionCallInvoke (& fcinfo );
855
867
868
+ MemoryContextSwitchTo (oldContext );
869
+
856
870
/*
857
871
* Trigger protocol allows function to return a null pointer,
858
872
* but NOT to set the isnull result flag.
@@ -865,7 +879,7 @@ ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
865
879
}
866
880
867
881
HeapTuple
868
- ExecBRInsertTriggers (Relation rel , HeapTuple trigtuple )
882
+ ExecBRInsertTriggers (EState * estate , Relation rel , HeapTuple trigtuple )
869
883
{
870
884
int ntrigs = rel -> trigdesc -> n_before_row [TRIGGER_EVENT_INSERT ];
871
885
Trigger * * trigger = rel -> trigdesc -> tg_before_row [TRIGGER_EVENT_INSERT ];
@@ -884,20 +898,20 @@ ExecBRInsertTriggers(Relation rel, HeapTuple trigtuple)
884
898
continue ;
885
899
LocTriggerData .tg_trigtuple = oldtuple = newtuple ;
886
900
LocTriggerData .tg_trigger = trigger [i ];
887
- newtuple = ExecCallTriggerFunc (trigger [i ], & LocTriggerData );
901
+ newtuple = ExecCallTriggerFunc (trigger [i ], & LocTriggerData ,
902
+ GetPerTupleMemoryContext (estate ));
903
+ if (oldtuple != newtuple && oldtuple != trigtuple )
904
+ heap_freetuple (oldtuple );
888
905
if (newtuple == NULL )
889
906
break ;
890
- else if (oldtuple != newtuple && oldtuple != trigtuple )
891
- heap_freetuple (oldtuple );
892
907
}
893
908
return newtuple ;
894
909
}
895
910
896
911
void
897
- ExecARInsertTriggers (Relation rel , HeapTuple trigtuple )
912
+ ExecARInsertTriggers (EState * estate , Relation rel , HeapTuple trigtuple )
898
913
{
899
914
DeferredTriggerSaveEvent (rel , TRIGGER_EVENT_INSERT , NULL , trigtuple );
900
- return ;
901
915
}
902
916
903
917
bool
@@ -926,7 +940,8 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
926
940
continue ;
927
941
LocTriggerData .tg_trigtuple = trigtuple ;
928
942
LocTriggerData .tg_trigger = trigger [i ];
929
- newtuple = ExecCallTriggerFunc (trigger [i ], & LocTriggerData );
943
+ newtuple = ExecCallTriggerFunc (trigger [i ], & LocTriggerData ,
944
+ GetPerTupleMemoryContext (estate ));
930
945
if (newtuple == NULL )
931
946
break ;
932
947
if (newtuple != trigtuple )
@@ -944,7 +959,7 @@ ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
944
959
HeapTuple trigtuple = GetTupleForTrigger (estate , tupleid , NULL );
945
960
946
961
DeferredTriggerSaveEvent (rel , TRIGGER_EVENT_DELETE , trigtuple , NULL );
947
- return ;
962
+ heap_freetuple ( trigtuple ) ;
948
963
}
949
964
950
965
HeapTuple
@@ -981,11 +996,12 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
981
996
LocTriggerData .tg_trigtuple = trigtuple ;
982
997
LocTriggerData .tg_newtuple = oldtuple = newtuple ;
983
998
LocTriggerData .tg_trigger = trigger [i ];
984
- newtuple = ExecCallTriggerFunc (trigger [i ], & LocTriggerData );
999
+ newtuple = ExecCallTriggerFunc (trigger [i ], & LocTriggerData ,
1000
+ GetPerTupleMemoryContext (estate ));
1001
+ if (oldtuple != newtuple && oldtuple != intuple )
1002
+ heap_freetuple (oldtuple );
985
1003
if (newtuple == NULL )
986
1004
break ;
987
- else if (oldtuple != newtuple && oldtuple != intuple )
988
- heap_freetuple (oldtuple );
989
1005
}
990
1006
heap_freetuple (trigtuple );
991
1007
return newtuple ;
@@ -998,7 +1014,7 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
998
1014
HeapTuple trigtuple = GetTupleForTrigger (estate , tupleid , NULL );
999
1015
1000
1016
DeferredTriggerSaveEvent (rel , TRIGGER_EVENT_UPDATE , trigtuple , newtuple );
1001
- return ;
1017
+ heap_freetuple ( trigtuple ) ;
1002
1018
}
1003
1019
1004
1020
@@ -1236,7 +1252,7 @@ deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
1236
1252
}
1237
1253
1238
1254
elog (ERROR ,
1239
- "deferredTriggerGetPreviousEvent() : event for tuple %s not found" ,
1255
+ "deferredTriggerGetPreviousEvent: event for tuple %s not found" ,
1240
1256
DatumGetCString (DirectFunctionCall1 (tidout , PointerGetDatum (ctid ))));
1241
1257
return NULL ;
1242
1258
}
@@ -1250,7 +1266,8 @@ deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
1250
1266
* ----------
1251
1267
*/
1252
1268
static void
1253
- deferredTriggerExecute (DeferredTriggerEvent event , int itemno )
1269
+ deferredTriggerExecute (DeferredTriggerEvent event , int itemno ,
1270
+ MemoryContext per_tuple_context )
1254
1271
{
1255
1272
Relation rel ;
1256
1273
TriggerData LocTriggerData ;
@@ -1271,15 +1288,15 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
1271
1288
ItemPointerCopy (& (event -> dte_oldctid ), & (oldtuple .t_self ));
1272
1289
heap_fetch (rel , SnapshotAny , & oldtuple , & oldbuffer );
1273
1290
if (!oldtuple .t_data )
1274
- elog (ERROR , "deferredTriggerExecute() : failed to fetch old tuple" );
1291
+ elog (ERROR , "deferredTriggerExecute: failed to fetch old tuple" );
1275
1292
}
1276
1293
1277
1294
if (ItemPointerIsValid (& (event -> dte_newctid )))
1278
1295
{
1279
1296
ItemPointerCopy (& (event -> dte_newctid ), & (newtuple .t_self ));
1280
1297
heap_fetch (rel , SnapshotAny , & newtuple , & newbuffer );
1281
1298
if (!newtuple .t_data )
1282
- elog (ERROR , "deferredTriggerExecute() : failed to fetch new tuple" );
1299
+ elog (ERROR , "deferredTriggerExecute: failed to fetch new tuple" );
1283
1300
}
1284
1301
1285
1302
/* ----------
@@ -1320,7 +1337,9 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
1320
1337
* updated tuple.
1321
1338
* ----------
1322
1339
*/
1323
- rettuple = ExecCallTriggerFunc (LocTriggerData .tg_trigger , & LocTriggerData );
1340
+ rettuple = ExecCallTriggerFunc (LocTriggerData .tg_trigger ,
1341
+ & LocTriggerData ,
1342
+ per_tuple_context );
1324
1343
if (rettuple != NULL && rettuple != & oldtuple && rettuple != & newtuple )
1325
1344
heap_freetuple (rettuple );
1326
1345
@@ -1359,6 +1378,7 @@ deferredTriggerInvokeEvents(bool immediate_only)
1359
1378
int still_deferred_ones ;
1360
1379
int eventno = -1 ;
1361
1380
int i ;
1381
+ MemoryContext per_tuple_context ;
1362
1382
1363
1383
/* ----------
1364
1384
* For now we process all events - to speedup transaction blocks
@@ -1369,10 +1389,21 @@ deferredTriggerInvokeEvents(bool immediate_only)
1369
1389
* SET CONSTRAINTS ... command finishes and calls EndQuery.
1370
1390
* ----------
1371
1391
*/
1392
+
1393
+ /* Make a per-tuple memory context for trigger function calls */
1394
+ per_tuple_context =
1395
+ AllocSetContextCreate (CurrentMemoryContext ,
1396
+ "DeferredTriggerTupleContext" ,
1397
+ 0 ,
1398
+ ALLOCSET_DEFAULT_INITSIZE ,
1399
+ ALLOCSET_DEFAULT_MAXSIZE );
1400
+
1372
1401
foreach (el , deftrig_events )
1373
1402
{
1374
1403
eventno ++ ;
1375
1404
1405
+ MemoryContextReset (per_tuple_context );
1406
+
1376
1407
/* ----------
1377
1408
* Get the event and check if it is completely done.
1378
1409
* ----------
@@ -1409,7 +1440,7 @@ deferredTriggerInvokeEvents(bool immediate_only)
1409
1440
* So let's fire it...
1410
1441
* ----------
1411
1442
*/
1412
- deferredTriggerExecute (event , i );
1443
+ deferredTriggerExecute (event , i , per_tuple_context );
1413
1444
event -> dte_item [i ].dti_state |= TRIGGER_DEFERRED_DONE ;
1414
1445
}
1415
1446
@@ -1421,6 +1452,8 @@ deferredTriggerInvokeEvents(bool immediate_only)
1421
1452
if (!still_deferred_ones )
1422
1453
event -> dte_event |= TRIGGER_DEFERRED_DONE ;
1423
1454
}
1455
+
1456
+ MemoryContextDelete (per_tuple_context );
1424
1457
}
1425
1458
1426
1459
@@ -1866,13 +1899,10 @@ DeferredTriggerSaveEvent(Relation rel, int event,
1866
1899
* Check if we're interested in this row at all
1867
1900
* ----------
1868
1901
*/
1869
- if (rel -> trigdesc -> n_after_row [TRIGGER_EVENT_INSERT ] == 0 &&
1870
- rel -> trigdesc -> n_after_row [TRIGGER_EVENT_UPDATE ] == 0 &&
1871
- rel -> trigdesc -> n_after_row [TRIGGER_EVENT_DELETE ] == 0 &&
1872
- rel -> trigdesc -> n_before_row [TRIGGER_EVENT_INSERT ] == 0 &&
1873
- rel -> trigdesc -> n_before_row [TRIGGER_EVENT_UPDATE ] == 0 &&
1874
- rel -> trigdesc -> n_before_row [TRIGGER_EVENT_DELETE ] == 0 )
1902
+ ntriggers = rel -> trigdesc -> n_after_row [event ];
1903
+ if (ntriggers <= 0 )
1875
1904
return ;
1905
+ triggers = rel -> trigdesc -> tg_after_row [event ];
1876
1906
1877
1907
/* ----------
1878
1908
* Get the CTID's of OLD and NEW
@@ -1893,9 +1923,6 @@ DeferredTriggerSaveEvent(Relation rel, int event,
1893
1923
*/
1894
1924
oldcxt = MemoryContextSwitchTo (deftrig_cxt );
1895
1925
1896
- ntriggers = rel -> trigdesc -> n_after_row [event ];
1897
- triggers = rel -> trigdesc -> tg_after_row [event ];
1898
-
1899
1926
new_size = sizeof (DeferredTriggerEventData ) +
1900
1927
ntriggers * sizeof (DeferredTriggerEventItem );
1901
1928
0 commit comments