@ -7,7 +7,7 @@
* Portions Copyright ( c ) 1994 , Regents of the University of California
*
* IDENTIFICATION
* $ Header : / cvsroot / pgsql / src / backend / commands / trigger . c , v 1.114 2002 / 04 / 19 16 : 36 : 08 tgl Exp $
* $ Header : / cvsroot / pgsql / src / backend / commands / trigger . c , v 1.115 2002 / 04 / 26 19 : 29 : 47 tgl Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -503,6 +503,123 @@ RelationRemoveTriggers(Relation rel)
heap_close ( tgrel , RowExclusiveLock ) ;
}
/*
* renametrig - changes the name of a trigger on a relation
*
* trigger name is changed in trigger catalog .
* No record of the previous name is kept .
*
* get proper relrelation from relation catalog ( if not arg )
* scan trigger catalog
* for name conflict ( within rel )
* for original trigger ( if not arg )
* modify tgname in trigger tuple
* insert modified trigger in trigger catalog
* delete original trigger from trigger catalog
*/
void
renametrig ( Oid relid ,
const char * oldname ,
const char * newname )
{
Relation targetrel ;
Relation tgrel ;
HeapTuple tuple ;
SysScanDesc tgscan ;
ScanKeyData key ;
bool found = FALSE ;
Relation idescs [ Num_pg_trigger_indices ] ;
/*
* Grab an exclusive lock on the target table , which we will NOT
* release until end of transaction .
*/
targetrel = heap_open ( relid , AccessExclusiveLock ) ;
/*
* Scan pg_trigger twice for existing triggers on relation . We do this in
* order to ensure a trigger does not exist with newname ( The unique index
* on tgrelid / tgname would complain anyway ) and to ensure a trigger does
* exist with oldname .
*
* NOTE that this is cool only because we have AccessExclusiveLock on the
* relation , so the trigger set won ' t be changing underneath us .
*/
tgrel = heap_openr ( TriggerRelationName , RowExclusiveLock ) ;
/*
* First pass - - look for name conflict
*/
ScanKeyEntryInitialize ( & key , 0 ,
Anum_pg_trigger_tgrelid ,
F_OIDEQ ,
ObjectIdGetDatum ( relid ) ) ;
tgscan = systable_beginscan ( tgrel , TriggerRelidNameIndex , true ,
SnapshotNow , 1 , & key ) ;
while ( HeapTupleIsValid ( tuple = systable_getnext ( tgscan ) ) )
{
Form_pg_trigger pg_trigger = ( Form_pg_trigger ) GETSTRUCT ( tuple ) ;
if ( namestrcmp ( & ( pg_trigger - > tgname ) , newname ) = = 0 )
elog ( ERROR , " renametrig: trigger %s already defined on relation %s " ,
newname , RelationGetRelationName ( targetrel ) ) ;
}
systable_endscan ( tgscan ) ;
/*
* Second pass - - look for trigger existing with oldname and update
*/
ScanKeyEntryInitialize ( & key , 0 ,
Anum_pg_trigger_tgrelid ,
F_OIDEQ ,
ObjectIdGetDatum ( relid ) ) ;
tgscan = systable_beginscan ( tgrel , TriggerRelidNameIndex , true ,
SnapshotNow , 1 , & key ) ;
while ( HeapTupleIsValid ( tuple = systable_getnext ( tgscan ) ) )
{
Form_pg_trigger pg_trigger = ( Form_pg_trigger ) GETSTRUCT ( tuple ) ;
if ( namestrcmp ( & ( pg_trigger - > tgname ) , oldname ) = = 0 )
{
/*
* Update pg_trigger tuple with new tgname .
* ( Scribbling on tuple is OK because it ' s a copy . . . )
*/
namestrcpy ( & ( pg_trigger - > tgname ) , newname ) ;
simple_heap_update ( tgrel , & tuple - > t_self , tuple ) ;
/*
* keep system catalog indices current
*/
CatalogOpenIndices ( Num_pg_trigger_indices , Name_pg_trigger_indices , idescs ) ;
CatalogIndexInsert ( idescs , Num_pg_trigger_indices , tgrel , tuple ) ;
CatalogCloseIndices ( Num_pg_trigger_indices , idescs ) ;
/*
* Invalidate relation ' s relcache entry so that other
* backends ( and this one too ! ) are sent SI message to make them
* rebuild relcache entries .
*/
CacheInvalidateRelcache ( relid ) ;
found = TRUE ;
break ;
}
}
systable_endscan ( tgscan ) ;
heap_close ( tgrel , RowExclusiveLock ) ;
if ( ! found )
elog ( ERROR , " renametrig: trigger %s not defined on relation %s " ,
oldname , RelationGetRelationName ( targetrel ) ) ;
/*
* Close rel , but keep exclusive lock !
*/
heap_close ( targetrel , NoLock ) ;
}
/*
* Build trigger data to attach to the given relcache entry .
*