7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
9
* IDENTIFICATION
10
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.239 2008/11/02 01:45:28 tgl Exp $
10
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.240 2008/11/09 21:24:32 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -95,7 +95,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
95
95
Oid funcoid ;
96
96
Oid funcrettype ;
97
97
Oid trigoid ;
98
- int found = 0 ;
99
98
int i ;
100
99
char constrtrigname [NAMEDATALEN ];
101
100
char * trigname ;
@@ -280,10 +279,9 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
280
279
}
281
280
282
281
/*
283
- * Scan pg_trigger for existing triggers on relation. We do this mainly
284
- * because we must count them; a secondary benefit is to give a nice error
285
- * message if there's already a trigger of the same name. (The unique
286
- * index on tgrelid/tgname would complain anyway.)
282
+ * Scan pg_trigger for existing triggers on relation. We do this only
283
+ * to give a nice error message if there's already a trigger of the same
284
+ * name. (The unique index on tgrelid/tgname would complain anyway.)
287
285
*
288
286
* NOTE that this is cool only because we have AccessExclusiveLock on the
289
287
* relation, so the trigger set won't be changing underneath us.
@@ -303,7 +301,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
303
301
(errcode (ERRCODE_DUPLICATE_OBJECT ),
304
302
errmsg ("trigger \"%s\" for relation \"%s\" already exists" ,
305
303
trigname , stmt -> relation -> relname )));
306
- found ++ ;
307
304
}
308
305
systable_endscan (tgscan );
309
306
@@ -405,7 +402,7 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
405
402
elog (ERROR , "cache lookup failed for relation %u" ,
406
403
RelationGetRelid (rel ));
407
404
408
- ((Form_pg_class ) GETSTRUCT (tuple ))-> reltriggers = found + 1 ;
405
+ ((Form_pg_class ) GETSTRUCT (tuple ))-> relhastriggers = true ;
409
406
410
407
simple_heap_update (pgrel , & tuple -> t_self , tuple );
411
408
@@ -818,9 +815,6 @@ RemoveTriggerById(Oid trigOid)
818
815
HeapTuple tup ;
819
816
Oid relid ;
820
817
Relation rel ;
821
- Relation pgrel ;
822
- HeapTuple tuple ;
823
- Form_pg_class classForm ;
824
818
825
819
tgrel = heap_open (TriggerRelationId , RowExclusiveLock );
826
820
@@ -867,33 +861,15 @@ RemoveTriggerById(Oid trigOid)
867
861
heap_close (tgrel , RowExclusiveLock );
868
862
869
863
/*
870
- * Update relation's pg_class entry. Crucial side-effect: other backends
871
- * (and this one too!) are sent SI message to make them rebuild relcache
872
- * entries.
873
- *
874
- * Note this is OK only because we have AccessExclusiveLock on the rel, so
875
- * no one else is creating/deleting triggers on this rel at the same time.
864
+ * We do not bother to try to determine whether any other triggers remain,
865
+ * which would be needed in order to decide whether it's safe to clear
866
+ * the relation's relhastriggers. (In any case, there might be a
867
+ * concurrent process adding new triggers.) Instead, just force a
868
+ * relcache inval to make other backends (and this one too!) rebuild
869
+ * their relcache entries. There's no great harm in leaving relhastriggers
870
+ * true even if there are no triggers left.
876
871
*/
877
- pgrel = heap_open (RelationRelationId , RowExclusiveLock );
878
- tuple = SearchSysCacheCopy (RELOID ,
879
- ObjectIdGetDatum (relid ),
880
- 0 , 0 , 0 );
881
- if (!HeapTupleIsValid (tuple ))
882
- elog (ERROR , "cache lookup failed for relation %u" , relid );
883
- classForm = (Form_pg_class ) GETSTRUCT (tuple );
884
-
885
- if (classForm -> reltriggers == 0 ) /* should not happen */
886
- elog (ERROR , "relation \"%s\" has reltriggers = 0" ,
887
- RelationGetRelationName (rel ));
888
- classForm -> reltriggers -- ;
889
-
890
- simple_heap_update (pgrel , & tuple -> t_self , tuple );
891
-
892
- CatalogUpdateIndexes (pgrel , tuple );
893
-
894
- heap_freetuple (tuple );
895
-
896
- heap_close (pgrel , RowExclusiveLock );
872
+ CacheInvalidateRelcache (rel );
897
873
898
874
/* Keep lock on trigger's rel until end of xact */
899
875
heap_close (rel , NoLock );
@@ -1134,18 +1110,23 @@ void
1134
1110
RelationBuildTriggers (Relation relation )
1135
1111
{
1136
1112
TriggerDesc * trigdesc ;
1137
- int ntrigs = relation -> rd_rel -> reltriggers ;
1113
+ int numtrigs ;
1114
+ int maxtrigs ;
1138
1115
Trigger * triggers ;
1139
- int found = 0 ;
1140
1116
Relation tgrel ;
1141
1117
ScanKeyData skey ;
1142
1118
SysScanDesc tgscan ;
1143
1119
HeapTuple htup ;
1144
1120
MemoryContext oldContext ;
1121
+ int i ;
1145
1122
1146
- Assert (ntrigs > 0 ); /* else I should not have been called */
1147
-
1148
- triggers = (Trigger * ) palloc (ntrigs * sizeof (Trigger ));
1123
+ /*
1124
+ * Allocate a working array to hold the triggers (the array is extended
1125
+ * if necessary)
1126
+ */
1127
+ maxtrigs = 16 ;
1128
+ triggers = (Trigger * ) palloc (maxtrigs * sizeof (Trigger ));
1129
+ numtrigs = 0 ;
1149
1130
1150
1131
/*
1151
1132
* Note: since we scan the triggers using TriggerRelidNameIndexId, we will
@@ -1167,10 +1148,12 @@ RelationBuildTriggers(Relation relation)
1167
1148
Form_pg_trigger pg_trigger = (Form_pg_trigger ) GETSTRUCT (htup );
1168
1149
Trigger * build ;
1169
1150
1170
- if (found >= ntrigs )
1171
- elog (ERROR , "too many trigger records found for relation \"%s\"" ,
1172
- RelationGetRelationName (relation ));
1173
- build = & (triggers [found ]);
1151
+ if (numtrigs >= maxtrigs )
1152
+ {
1153
+ maxtrigs *= 2 ;
1154
+ triggers = (Trigger * ) repalloc (triggers , maxtrigs * sizeof (Trigger ));
1155
+ }
1156
+ build = & (triggers [numtrigs ]);
1174
1157
1175
1158
build -> tgoid = HeapTupleGetOid (htup );
1176
1159
build -> tgname = DatumGetCString (DirectFunctionCall1 (nameout ,
@@ -1199,7 +1182,6 @@ RelationBuildTriggers(Relation relation)
1199
1182
bytea * val ;
1200
1183
bool isnull ;
1201
1184
char * p ;
1202
- int i ;
1203
1185
1204
1186
val = DatumGetByteaP (fastgetattr (htup ,
1205
1187
Anum_pg_trigger_tgargs ,
@@ -1218,23 +1200,25 @@ RelationBuildTriggers(Relation relation)
1218
1200
else
1219
1201
build -> tgargs = NULL ;
1220
1202
1221
- found ++ ;
1203
+ numtrigs ++ ;
1222
1204
}
1223
1205
1224
1206
systable_endscan (tgscan );
1225
1207
heap_close (tgrel , AccessShareLock );
1226
1208
1227
- if (found != ntrigs )
1228
- elog (ERROR , "%d trigger record(s) not found for relation \"%s\"" ,
1229
- ntrigs - found ,
1230
- RelationGetRelationName (relation ));
1209
+ /* There might not be any triggers */
1210
+ if (numtrigs == 0 )
1211
+ {
1212
+ pfree (triggers );
1213
+ return ;
1214
+ }
1231
1215
1232
1216
/* Build trigdesc */
1233
1217
trigdesc = (TriggerDesc * ) palloc0 (sizeof (TriggerDesc ));
1234
1218
trigdesc -> triggers = triggers ;
1235
- trigdesc -> numtriggers = ntrigs ;
1236
- for (found = 0 ; found < ntrigs ; found ++ )
1237
- InsertTrigger (trigdesc , & (triggers [found ]), found );
1219
+ trigdesc -> numtriggers = numtrigs ;
1220
+ for (i = 0 ; i < numtrigs ; i ++ )
1221
+ InsertTrigger (trigdesc , & (triggers [i ]), i );
1238
1222
1239
1223
/* Copy completed trigdesc into cache storage */
1240
1224
oldContext = MemoryContextSwitchTo (CacheMemoryContext );
0 commit comments