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.217 2007/08/15 19:15:46 tgl Exp $
10
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.218 2007/08/15 21:39:50 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -2313,11 +2313,10 @@ afterTriggerMarkEvents(AfterTriggerEventList *events,
2313
2313
* Scan the given event list for events that are marked as to be fired
2314
2314
* in the current firing cycle, and fire them.
2315
2315
*
2316
- * If estate isn't NULL, then we expect that all the firable events are
2317
- * for triggers of the relations included in the estate's result relation
2318
- * array. This allows us to re-use the estate's open relations and
2319
- * trigger cache info. When estate is NULL, we have to find the relations
2320
- * the hard way.
2316
+ * If estate isn't NULL, we use its result relation info to avoid repeated
2317
+ * openings and closing of trigger target relations. If it is NULL, we
2318
+ * make one locally to cache the info in case there are multiple trigger
2319
+ * events per rel.
2321
2320
*
2322
2321
* When delete_ok is TRUE, it's okay to delete fully-processed events.
2323
2322
* The events list pointers are updated.
@@ -2332,12 +2331,19 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
2332
2331
AfterTriggerEvent event ,
2333
2332
prev_event ;
2334
2333
MemoryContext per_tuple_context ;
2335
- bool locally_opened = false;
2334
+ bool local_estate = false;
2336
2335
Relation rel = NULL ;
2337
2336
TriggerDesc * trigdesc = NULL ;
2338
2337
FmgrInfo * finfo = NULL ;
2339
2338
Instrumentation * instr = NULL ;
2340
2339
2340
+ /* Make a local EState if need be */
2341
+ if (estate == NULL )
2342
+ {
2343
+ estate = CreateExecutorState ();
2344
+ local_estate = true;
2345
+ }
2346
+
2341
2347
/* Make a per-tuple memory context for trigger function calls */
2342
2348
per_tuple_context =
2343
2349
AllocSetContextCreate (CurrentMemoryContext ,
@@ -2360,77 +2366,21 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
2360
2366
event -> ate_firing_id == firing_id )
2361
2367
{
2362
2368
/*
2363
- * So let's fire it... but first, open the correct relation if
2369
+ * So let's fire it... but first, find the correct relation if
2364
2370
* this is not the same relation as before.
2365
2371
*/
2366
- if (rel == NULL || rel -> rd_id != event -> ate_relid )
2372
+ if (rel == NULL || RelationGetRelid ( rel ) != event -> ate_relid )
2367
2373
{
2368
- if (locally_opened )
2369
- {
2370
- /* close prior rel if any */
2371
- if (rel )
2372
- heap_close (rel , NoLock );
2373
- if (trigdesc )
2374
- FreeTriggerDesc (trigdesc );
2375
- if (finfo )
2376
- pfree (finfo );
2377
- Assert (instr == NULL ); /* never used in this case */
2378
- }
2379
- locally_opened = true;
2380
-
2381
- if (estate )
2382
- {
2383
- /* Find target relation among estate's result rels */
2384
- ResultRelInfo * rInfo ;
2385
- int nr ;
2386
-
2387
- rInfo = estate -> es_result_relations ;
2388
- nr = estate -> es_num_result_relations ;
2389
- while (nr > 0 )
2390
- {
2391
- if (rInfo -> ri_RelationDesc -> rd_id == event -> ate_relid )
2392
- {
2393
- rel = rInfo -> ri_RelationDesc ;
2394
- trigdesc = rInfo -> ri_TrigDesc ;
2395
- finfo = rInfo -> ri_TrigFunctions ;
2396
- instr = rInfo -> ri_TrigInstrument ;
2397
- locally_opened = false;
2398
- break ;
2399
- }
2400
- rInfo ++ ;
2401
- nr -- ;
2402
- }
2403
- }
2404
-
2405
- if (locally_opened )
2406
- {
2407
- /* Hard way: open target relation for ourselves */
2408
-
2409
- /*
2410
- * We assume that an appropriate lock is still held by the
2411
- * executor, so grab no new lock here.
2412
- */
2413
- rel = heap_open (event -> ate_relid , NoLock );
2414
-
2415
- /*
2416
- * Copy relation's trigger info so that we have a stable
2417
- * copy no matter what the called triggers do.
2418
- */
2419
- trigdesc = CopyTriggerDesc (rel -> trigdesc );
2420
-
2421
- if (trigdesc == NULL ) /* should not happen */
2422
- elog (ERROR , "relation %u has no triggers" ,
2423
- event -> ate_relid );
2424
-
2425
- /*
2426
- * Allocate space to cache fmgr lookup info for triggers.
2427
- */
2428
- finfo = (FmgrInfo * )
2429
- palloc0 (trigdesc -> numtriggers * sizeof (FmgrInfo ));
2430
-
2431
- /* Never any EXPLAIN info in this case */
2432
- instr = NULL ;
2433
- }
2374
+ ResultRelInfo * rInfo ;
2375
+
2376
+ rInfo = ExecGetTriggerResultRel (estate , event -> ate_relid );
2377
+ rel = rInfo -> ri_RelationDesc ;
2378
+ trigdesc = rInfo -> ri_TrigDesc ;
2379
+ finfo = rInfo -> ri_TrigFunctions ;
2380
+ instr = rInfo -> ri_TrigInstrument ;
2381
+ if (trigdesc == NULL ) /* should not happen */
2382
+ elog (ERROR , "relation %u has no triggers" ,
2383
+ event -> ate_relid );
2434
2384
}
2435
2385
2436
2386
/*
@@ -2480,17 +2430,22 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
2480
2430
events -> tail = prev_event ;
2481
2431
2482
2432
/* Release working resources */
2483
- if (locally_opened )
2433
+ MemoryContextDelete (per_tuple_context );
2434
+
2435
+ if (local_estate )
2484
2436
{
2485
- if (rel )
2486
- heap_close (rel , NoLock );
2487
- if (trigdesc )
2488
- FreeTriggerDesc (trigdesc );
2489
- if (finfo )
2490
- pfree (finfo );
2491
- Assert (instr == NULL ); /* never used in this case */
2437
+ ListCell * l ;
2438
+
2439
+ foreach (l , estate -> es_trig_target_relations )
2440
+ {
2441
+ ResultRelInfo * resultRelInfo = (ResultRelInfo * ) lfirst (l );
2442
+
2443
+ /* Close indices and then the relation itself */
2444
+ ExecCloseIndices (resultRelInfo );
2445
+ heap_close (resultRelInfo -> ri_RelationDesc , NoLock );
2446
+ }
2447
+ FreeExecutorState (estate );
2492
2448
}
2493
- MemoryContextDelete (per_tuple_context );
2494
2449
}
2495
2450
2496
2451
0 commit comments