Skip to content

Commit 3be6367

Browse files
committed
This patch creates a function named pg_get_triggerdef that takes the oid of
a trigger as its parameter. It is basically copied from the pg_dump code. Christopher Kings-Lynne
1 parent 8819213 commit 3be6367

File tree

4 files changed

+203
-8
lines changed

4 files changed

+203
-8
lines changed

doc/src/sgml/func.sgml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.144 2003/03/20 03:34:55 momjian Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.145 2003/03/20 18:58:02 momjian Exp $
33
PostgreSQL documentation
44
-->
55

@@ -6795,6 +6795,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
67956795
<primary>pg_get_indexdef</primary>
67966796
</indexterm>
67976797

6798+
<indexterm zone="functions-misc">
6799+
<primary>pg_get_triggerdef</primary>
6800+
</indexterm>
6801+
67986802
<indexterm zone="functions-misc">
67996803
<primary>pg_get_constraintdef</primary>
68006804
</indexterm>
@@ -6808,13 +6812,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
68086812
extract information from the system catalogs.
68096813
<function>pg_get_viewdef</function>,
68106814
<function>pg_get_ruledef</function>,
6811-
<function>pg_get_indexdef</function>, and
6815+
<function>pg_get_indexdef()</function>,
6816+
<function>pg_get_triggerdef()</function>, and
68126817
<function>pg_get_constraintdef</function> respectively
68136818
reconstruct the creating command for a view, rule, index, or
68146819
constraint. (Note that this is a decompiled reconstruction, not
6815-
the verbatim text of the command.) At present
6816-
<function>pg_get_constraintdef</function> only works for
6817-
foreign-key constraints. <function>pg_get_userbyid</function>
6820+
the verbatim text of the command.)
6821+
<function>pg_get_userbyid</function>
68186822
extracts a user's name given a user ID number.
68196823
</para>
68206824

@@ -6846,6 +6850,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
68466850
<entry><type>text</type></entry>
68476851
<entry>get <command>CREATE INDEX</> command for index</entry>
68486852
</row>
6853+
<row>
6854+
<entry><function>pg_get_triggerdef</function>(<parameter>triggerOID</parameter>)</entry>
6855+
<entry><type>text</type></entry>
6856+
<entry>Get <command>CREATE [ CONSTRAINT ] TRIGGER</> command for trigger</entry>
6857+
</row>
68496858
<row>
68506859
<entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>)</literal></entry>
68516860
<entry><type>text</type></entry>

src/backend/utils/adt/ruleutils.c

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* back to source text
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.136 2003/02/16 02:30:39 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.137 2003/03/20 18:58:02 momjian Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -49,6 +49,7 @@
4949
#include "catalog/pg_cast.h"
5050
#include "catalog/pg_constraint.h"
5151
#include "catalog/pg_index.h"
52+
#include "catalog/pg_trigger.h"
5253
#include "catalog/pg_opclass.h"
5354
#include "catalog/pg_operator.h"
5455
#include "catalog/pg_shadow.h"
@@ -369,6 +370,188 @@ pg_do_getviewdef(Oid viewoid)
369370
return ruledef;
370371
}
371372

373+
/* ----------
374+
* get_triggerdef - Get the definition of a trigger
375+
* ----------
376+
*/
377+
Datum
378+
pg_get_triggerdef(PG_FUNCTION_ARGS)
379+
{
380+
Oid trigid = PG_GETARG_OID(0);
381+
text *trigdef;
382+
HeapTuple ht_trig;
383+
HeapTuple ht_proc;
384+
Form_pg_trigger trigrec;
385+
int len;
386+
StringInfoData 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;
394+
char *tgname;
395+
396+
/*
397+
* Fetch the pg_trigger tuple by the Oid of the trigger
398+
*/
399+
tgrel = heap_openr(TriggerRelationName, AccessShareLock);
400+
401+
/*
402+
* Find the trigger
403+
*/
404+
ScanKeyEntryInitialize(&skey[0], 0x0,
405+
ObjectIdAttributeNumber, F_OIDEQ,
406+
ObjectIdGetDatum(trigid));
407+
408+
tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
409+
SnapshotNow, 1, skey);
410+
411+
ht_trig = systable_getnext(tgscan);
412+
413+
if (!HeapTupleIsValid(ht_trig))
414+
elog(ERROR, "pg_get_triggerdef: there is no trigger with oid %u",
415+
trigid);
416+
417+
trigrec = (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);
430+
431+
/*
432+
* Start the trigger definition. Note that the trigger's name should
433+
* never be schema-qualified, but the trigger rel's name may be.
434+
*/
435+
initStringInfo(&buf);
436+
437+
tgname = NameStr(trigrec->tgname);
438+
appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
439+
trigrec->tgisconstraint ? "CONSTRAINT " : "",
440+
quote_identifier(tgname));
441+
442+
if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
443+
appendStringInfo(&buf, "BEFORE");
444+
else
445+
appendStringInfo(&buf, "AFTER");
446+
if (TRIGGER_FOR_INSERT(trigrec->tgtype))
447+
{
448+
appendStringInfo(&buf, " INSERT");
449+
findx++;
450+
}
451+
if (TRIGGER_FOR_DELETE(trigrec->tgtype))
452+
{
453+
if (findx > 0)
454+
appendStringInfo(&buf, " OR DELETE");
455+
else
456+
appendStringInfo(&buf, " DELETE");
457+
findx++;
458+
}
459+
if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
460+
{
461+
if (findx > 0)
462+
appendStringInfo(&buf, " OR UPDATE");
463+
else
464+
appendStringInfo(&buf, " UPDATE");
465+
}
466+
appendStringInfo(&buf, " ON %s ",
467+
generate_relation_name(trigrec->tgrelid));
468+
469+
470+
if (trigrec->tgisconstraint)
471+
{
472+
if (trigrec->tgconstrrelid != 0)
473+
{
474+
appendStringInfo(&buf, "FROM %s ",
475+
generate_relation_name(trigrec->tgconstrrelid));
476+
}
477+
if (!trigrec->tgdeferrable)
478+
appendStringInfo(&buf, "NOT ");
479+
appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
480+
if (trigrec->tginitdeferred)
481+
appendStringInfo(&buf, "DEFERRED ");
482+
else
483+
appendStringInfo(&buf, "IMMEDIATE ");
484+
485+
}
486+
487+
if (TRIGGER_FOR_ROW(trigrec->tgtype))
488+
appendStringInfo(&buf, "FOR EACH ROW ");
489+
else
490+
appendStringInfo(&buf, "FOR EACH STATEMENT ");
491+
492+
appendStringInfo(&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;;)
507+
{
508+
p = strchr(p, '\\');
509+
if (p == NULL)
510+
{
511+
elog(ERROR, "pg_get_triggerdef: bad argument string for trigger");
512+
}
513+
p++;
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++);
530+
}
531+
appendStringInfoChar(&buf, '\'');
532+
appendStringInfo(&buf, (findx < trigrec->tgnargs - 1) ? ", " : "");
533+
tgargs = p + 4;
534+
}
535+
536+
/* Deliberately omit semi-colon */
537+
appendStringInfo(&buf, ")");
538+
539+
/*
540+
* Create the result as a TEXT datum, and free working data
541+
*/
542+
len = buf.len + VARHDRSZ;
543+
trigdef = (text *) palloc(len);
544+
VARATT_SIZEP(trigdef) = len;
545+
memcpy(VARDATA(trigdef), buf.data, buf.len);
546+
547+
pfree(buf.data);
548+
549+
ReleaseSysCache(ht_trig);
550+
ReleaseSysCache(ht_proc);
551+
heap_close(tgrel, AccessShareLock);
552+
553+
PG_RETURN_TEXT_P(trigdef);
554+
}
372555

373556
/* ----------
374557
* get_indexdef - Get the definition of an index

src/include/catalog/pg_proc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: pg_proc.h,v 1.288 2003/03/20 03:34:56 momjian Exp $
10+
* $Id: pg_proc.h,v 1.289 2003/03/20 18:58:02 momjian Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -2194,6 +2194,8 @@ DATA(insert OID = 1642 ( pg_get_userbyid PGNSP PGUID 12 f f t f s 1 19 "23"
21942194
DESCR("user name by UID (with fallback)");
21952195
DATA(insert OID = 1643 ( pg_get_indexdef PGNSP PGUID 12 f f t f s 1 25 "26" pg_get_indexdef - _null_ ));
21962196
DESCR("index description");
2197+
DATA(insert OID = 1662 ( pg_get_triggerdef PGNSP PGUID 12 f f t f s 1 25 "26" pg_get_triggerdef - _null_ ));
2198+
DESCR("trigger description");
21972199
DATA(insert OID = 1387 ( pg_get_constraintdef PGNSP PGUID 12 f f t f s 1 25 "26" pg_get_constraintdef - _null_ ));
21982200
DESCR("constraint description");
21992201
DATA(insert OID = 1716 ( pg_get_expr PGNSP PGUID 12 f f t f s 2 25 "25 26" pg_get_expr - _null_ ));

src/include/utils/builtins.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: builtins.h,v 1.208 2003/02/13 05:24:04 momjian Exp $
10+
* $Id: builtins.h,v 1.209 2003/03/20 18:58:02 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -399,6 +399,7 @@ extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
399399
extern Datum pg_get_viewdef(PG_FUNCTION_ARGS);
400400
extern Datum pg_get_viewdef_name(PG_FUNCTION_ARGS);
401401
extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
402+
extern Datum pg_get_triggerdef(PG_FUNCTION_ARGS);
402403
extern Datum pg_get_constraintdef(PG_FUNCTION_ARGS);
403404
extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
404405
extern Datum pg_get_expr(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy