33 *back to source text
44 *
55 * IDENTIFICATION
6- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.139 2003/04/24 21:16:43 tgl Exp $
6+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.140 2003/05/20 20:35:10 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
4949#include "catalog/pg_cast.h"
5050#include "catalog/pg_constraint.h"
5151#include "catalog/pg_index.h"
52- #include "catalog/pg_trigger.h"
5352#include "catalog/pg_opclass.h"
5453#include "catalog/pg_operator.h"
5554#include "catalog/pg_shadow.h"
55+ #include "catalog/pg_trigger.h"
5656#include "executor/spi.h"
5757#include "lib/stringinfo.h"
5858#include "nodes/makefuncs.h"
@@ -380,53 +380,34 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
380380Oid trigid = PG_GETARG_OID (0 );
381381text * trigdef ;
382382HeapTuple ht_trig ;
383- HeapTuple ht_proc ;
384383Form_pg_trigger trigrec ;
385384int len ;
386385StringInfoData buf ;
387- Relation tgrel ;
388- ScanKeyData skey [1 ];
389- SysScanDesc tgscan ;
390- int findx = 0 ;
391- const char * tgargs ;
392- const char * p ;
393- char * tgfname ;
386+ Relation tgrel ;
387+ ScanKeyData skey [1 ];
388+ SysScanDesc tgscan ;
389+ int findx = 0 ;
394390char * tgname ;
395391
396392/*
397393 * Fetch the pg_trigger tuple by the Oid of the trigger
398394 */
399- tgrel = heap_openr (TriggerRelationName ,AccessShareLock );
395+ tgrel = heap_openr (TriggerRelationName ,AccessShareLock );
400396
401- /*
402- * Find the trigger
403- */
404- ScanKeyEntryInitialize (& skey [0 ],0x0 ,
405- ObjectIdAttributeNumber ,F_OIDEQ ,
406- ObjectIdGetDatum (trigid ));
397+ ScanKeyEntryInitialize (& skey [0 ],0x0 ,
398+ ObjectIdAttributeNumber ,F_OIDEQ ,
399+ ObjectIdGetDatum (trigid ));
407400
408- tgscan = systable_beginscan (tgrel ,TriggerOidIndex , true,
409- SnapshotNow ,1 ,skey );
401+ tgscan = systable_beginscan (tgrel ,TriggerOidIndex , true,
402+ SnapshotNow ,1 ,skey );
410403
411- ht_trig = systable_getnext (tgscan );
404+ ht_trig = systable_getnext (tgscan );
412405
413- if (!HeapTupleIsValid (ht_trig ))
414- elog (ERROR ,"pg_get_triggerdef: there is no trigger with oid %u" ,
415- trigid );
406+ if (!HeapTupleIsValid (ht_trig ))
407+ elog (ERROR ,"pg_get_triggerdef: there is no trigger with oid %u" ,
408+ trigid );
416409
417410trigrec = (Form_pg_trigger )GETSTRUCT (ht_trig );
418- systable_endscan (tgscan );
419-
420- /*
421- * Fetch the pg_proc tuple of the trigger's function
422- */
423- ht_proc = SearchSysCache (PROCOID ,
424- ObjectIdGetDatum (trigrec -> tgfoid ),
425- 0 ,0 ,0 );
426- if (!HeapTupleIsValid (ht_proc ))
427- elog (ERROR ,"syscache lookup for function %u failed" ,trigrec -> tgfoid );
428-
429- tgfname = NameStr (((Form_pg_proc )GETSTRUCT (ht_proc ))-> proname );
430411
431412/*
432413 * Start the trigger definition. Note that the trigger's name should
@@ -464,16 +445,13 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
464445appendStringInfo (& buf ," UPDATE" );
465446}
466447appendStringInfo (& buf ," ON %s " ,
467- generate_relation_name (trigrec -> tgrelid ));
468-
448+ generate_relation_name (trigrec -> tgrelid ));
469449
470450if (trigrec -> tgisconstraint )
471451{
472- if (trigrec -> tgconstrrelid != 0 )
473- {
452+ if (trigrec -> tgconstrrelid != InvalidOid )
474453appendStringInfo (& buf ,"FROM %s " ,
475- generate_relation_name (trigrec -> tgconstrrelid ));
476- }
454+ generate_relation_name (trigrec -> tgconstrrelid ));
477455if (!trigrec -> tgdeferrable )
478456appendStringInfo (& buf ,"NOT " );
479457appendStringInfo (& buf ,"DEFERRABLE INITIALLY " );
@@ -490,50 +468,39 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
490468appendStringInfo (& buf ,"FOR EACH STATEMENT " );
491469
492470appendStringInfo (& buf ,"EXECUTE PROCEDURE %s(" ,
493- quote_identifier (tgfname ));
494-
495- /* Get args string */
496- tgargs = DatumGetCString (DirectFunctionCall1 (byteaout ,
497- PointerGetDatum (& trigrec -> tgargs )));
498- /* If it's NULL, fail */
499- if (tgargs == NULL )
500- elog (ERROR ,"pg_get_triggerdef: tgargs is NULL" );
501-
502- for (findx = 0 ;findx < trigrec -> tgnargs ;findx ++ )
503- {
504- const char * s ;
505-
506- for (p = tgargs ;;)
471+ generate_function_name (trigrec -> tgfoid ,0 ,NULL ));
472+
473+ if (trigrec -> tgnargs > 0 )
474+ {
475+ bytea * val ;
476+ bool isnull ;
477+ char * p ;
478+ int i ;
479+
480+ val = (bytea * )fastgetattr (ht_trig ,
481+ Anum_pg_trigger_tgargs ,
482+ tgrel -> rd_att ,& isnull );
483+ if (isnull )
484+ elog (ERROR ,"tgargs is null for trigger %u" ,trigid );
485+ p = (char * )VARDATA (val );
486+ for (i = 0 ;i < trigrec -> tgnargs ;i ++ )
507487{
508- p = strchr (p ,'\\' );
509- if (p == NULL )
488+ if (i > 0 )
489+ appendStringInfo (& buf ,", " );
490+ appendStringInfoChar (& buf ,'\'' );
491+ while (* p )
510492{
511- elog (ERROR ,"pg_get_triggerdef: bad argument string for trigger" );
493+ /* escape quotes and backslashes */
494+ if (* p == '\'' || * p == '\\' )
495+ appendStringInfoChar (& buf ,'\\' );
496+ appendStringInfoChar (& buf ,* p ++ );
512497}
513498p ++ ;
514- if (* p == '\\' )
515- {
516- p ++ ;
517- continue ;
518- }
519- if (p [0 ]== '0' && p [1 ]== '0' && p [2 ]== '0' )
520- break ;
521- }
522- p -- ;
523- appendStringInfoChar (& buf ,'\'' );
524- for (s = tgargs ;s < p ;)
525- {
526- /* If character is an apostrophe, escape it */
527- if (* s == '\'' )
528- appendStringInfoChar (& buf ,'\\' );
529- appendStringInfoChar (& buf ,* s ++ );
499+ appendStringInfoChar (& buf ,'\'' );
530500}
531- appendStringInfoChar (& buf ,'\'' );
532- appendStringInfo (& buf , (findx < trigrec -> tgnargs - 1 ) ?", " :"" );
533- tgargs = p + 4 ;
534501}
535502
536- /*Deliberately omit semi-colon */
503+ /*We deliberately do not put semi-colon at end */
537504appendStringInfo (& buf ,")" );
538505
539506/*
@@ -546,8 +513,8 @@ pg_get_triggerdef(PG_FUNCTION_ARGS)
546513
547514pfree (buf .data );
548515
549- ReleaseSysCache ( ht_trig );
550- ReleaseSysCache ( ht_proc );
516+ systable_endscan ( tgscan );
517+
551518heap_close (tgrel ,AccessShareLock );
552519
553520PG_RETURN_TEXT_P (trigdef );