diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 256b0fa3fae42e52e5d5abeab52c250743732b07..27966276d0e14bc4d52542fdc7b5ffadb4f17764 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.144 2003/03/20 03:34:55 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.145 2003/03/20 18:58:02 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -6795,6 +6795,10 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
     <primary>pg_get_indexdef</primary>
    </indexterm>
 
+   <indexterm zone="functions-misc">
+    <primary>pg_get_triggerdef</primary>
+   </indexterm>
+
    <indexterm zone="functions-misc">
     <primary>pg_get_constraintdef</primary>
    </indexterm>
@@ -6808,13 +6812,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
    extract information from the system catalogs.
    <function>pg_get_viewdef</function>,
    <function>pg_get_ruledef</function>,
-   <function>pg_get_indexdef</function>, and
+   <function>pg_get_indexdef()</function>,
+   <function>pg_get_triggerdef()</function>, and
    <function>pg_get_constraintdef</function> respectively
    reconstruct the creating command for a view, rule, index, or
    constraint.  (Note that this is a decompiled reconstruction, not
-   the verbatim text of the command.)  At present
-   <function>pg_get_constraintdef</function> only works for
-   foreign-key constraints.  <function>pg_get_userbyid</function>
+   the verbatim text of the command.)
+   <function>pg_get_userbyid</function>
    extracts a user's name given a user ID number.
   </para>
 
@@ -6846,6 +6850,11 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
        <entry><type>text</type></entry>
        <entry>get <command>CREATE INDEX</> command for index</entry>
       </row>
+      <row>
+       <entry><function>pg_get_triggerdef</function>(<parameter>triggerOID</parameter>)</entry>
+       <entry><type>text</type></entry>
+       <entry>Get <command>CREATE [ CONSTRAINT ] TRIGGER</> command for trigger</entry>
+      </row>
       <row>
        <entry><literal><function>pg_get_constraintdef</function>(<parameter>constraint_oid</parameter>)</literal></entry>
        <entry><type>text</type></entry>
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index dfed27f89dab7a8ab2d061d02ce35924258237a3..9b34544a3872313561739f6295ea6af9e5b08394 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
  *				back to source text
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.136 2003/02/16 02:30:39 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.137 2003/03/20 18:58:02 momjian Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -49,6 +49,7 @@
 #include "catalog/pg_cast.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_index.h"
+#include "catalog/pg_trigger.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_shadow.h"
@@ -369,6 +370,188 @@ pg_do_getviewdef(Oid viewoid)
 	return ruledef;
 }
 
+/* ----------
+ * get_triggerdef			- Get the definition of a trigger
+ * ----------
+ */
+Datum
+pg_get_triggerdef(PG_FUNCTION_ARGS)
+{
+	Oid			trigid = PG_GETARG_OID(0);
+	text	   *trigdef;
+	HeapTuple	ht_trig;
+	HeapTuple	ht_proc;
+	Form_pg_trigger trigrec;
+	int			len;
+	StringInfoData buf;
+        Relation        tgrel;
+        ScanKeyData skey[1];
+        SysScanDesc tgscan;
+	int		findx = 0;
+	const char *tgargs;
+	const char *p;
+	char 		*tgfname;
+	char 		*tgname;
+
+	/*
+	 * Fetch the pg_trigger tuple by the Oid of the trigger
+	 */
+        tgrel = heap_openr(TriggerRelationName, AccessShareLock);
+
+        /*
+         * Find the trigger
+         */
+        ScanKeyEntryInitialize(&skey[0], 0x0,
+                                                   ObjectIdAttributeNumber, F_OIDEQ,
+                                                   ObjectIdGetDatum(trigid));
+
+        tgscan = systable_beginscan(tgrel, TriggerOidIndex, true,
+                                                                SnapshotNow, 1, skey);
+
+        ht_trig = systable_getnext(tgscan);
+
+        if (!HeapTupleIsValid(ht_trig))
+                elog(ERROR, "pg_get_triggerdef: there is no trigger with oid %u",
+                         trigid);
+
+	trigrec = (Form_pg_trigger) GETSTRUCT(ht_trig);
+	systable_endscan(tgscan);
+
+	/*
+	 * Fetch the pg_proc tuple of the trigger's function
+	 */
+	ht_proc = SearchSysCache(PROCOID,
+						   ObjectIdGetDatum(trigrec->tgfoid),
+						   0, 0, 0);
+	if (!HeapTupleIsValid(ht_proc))
+		elog(ERROR, "syscache lookup for function %u failed", trigrec->tgfoid);
+
+	tgfname = NameStr(((Form_pg_proc) GETSTRUCT(ht_proc))->proname);
+
+	/*
+	 * Start the trigger definition. Note that the trigger's name should
+	 * never be schema-qualified, but the trigger rel's name may be.
+	 */
+	initStringInfo(&buf);
+
+	tgname = NameStr(trigrec->tgname);
+	appendStringInfo(&buf, "CREATE %sTRIGGER %s ",
+					 trigrec->tgisconstraint ? "CONSTRAINT " : "",
+					 quote_identifier(tgname));
+
+	if (TRIGGER_FOR_BEFORE(trigrec->tgtype))
+		appendStringInfo(&buf, "BEFORE");
+	else
+		appendStringInfo(&buf, "AFTER");
+	if (TRIGGER_FOR_INSERT(trigrec->tgtype))
+	{
+		appendStringInfo(&buf, " INSERT");
+		findx++;
+	}
+	if (TRIGGER_FOR_DELETE(trigrec->tgtype))
+	{
+		if (findx > 0)
+			appendStringInfo(&buf, " OR DELETE");
+		else
+			appendStringInfo(&buf, " DELETE");
+		findx++;
+	}
+	if (TRIGGER_FOR_UPDATE(trigrec->tgtype))
+	{
+		if (findx > 0)
+			appendStringInfo(&buf, " OR UPDATE");
+		else
+			appendStringInfo(&buf, " UPDATE");
+	}
+	appendStringInfo(&buf, " ON %s ",
+					generate_relation_name(trigrec->tgrelid));
+
+
+	if (trigrec->tgisconstraint)
+	{
+		if (trigrec->tgconstrrelid != 0)
+		{
+			appendStringInfo(&buf, "FROM %s ",
+					generate_relation_name(trigrec->tgconstrrelid));
+		}
+		if (!trigrec->tgdeferrable)
+			appendStringInfo(&buf, "NOT ");
+		appendStringInfo(&buf, "DEFERRABLE INITIALLY ");
+		if (trigrec->tginitdeferred)
+			appendStringInfo(&buf, "DEFERRED ");
+		else
+			appendStringInfo(&buf, "IMMEDIATE ");
+
+	}
+
+	if (TRIGGER_FOR_ROW(trigrec->tgtype))
+		appendStringInfo(&buf, "FOR EACH ROW ");
+	else
+		appendStringInfo(&buf, "FOR EACH STATEMENT ");
+
+	appendStringInfo(&buf, "EXECUTE PROCEDURE %s(",
+					quote_identifier(tgfname));
+
+	/* Get args string */
+	tgargs = DatumGetCString(DirectFunctionCall1(byteaout,
+								PointerGetDatum(&trigrec->tgargs)));
+	/* If it's NULL, fail */
+	if (tgargs == NULL)
+		elog(ERROR, "pg_get_triggerdef: tgargs is NULL");
+
+	for (findx = 0; findx < trigrec->tgnargs; findx++)
+	{
+		const char *s;
+
+		for (p = tgargs;;)
+		{
+			p = strchr(p, '\\');
+			if (p == NULL)
+			{
+				elog(ERROR, "pg_get_triggerdef: bad argument string for trigger");
+			}
+			p++;
+			if (*p == '\\')
+			{
+				p++;
+				continue;
+			}
+			if (p[0] == '0' && p[1] == '0' && p[2] == '0')
+				break;
+		}
+		p--;
+		appendStringInfoChar(&buf, '\'');
+		for (s = tgargs; s < p;)
+		{
+			/* If character is an apostrophe, escape it */
+			if (*s == '\'')
+				appendStringInfoChar(&buf, '\\');
+			appendStringInfoChar(&buf, *s++);
+		}
+		appendStringInfoChar(&buf, '\'');
+		appendStringInfo(&buf, (findx < trigrec->tgnargs - 1) ? ", " : "");
+		tgargs = p + 4;
+	}
+
+	/* Deliberately omit semi-colon */
+	appendStringInfo(&buf, ")");
+
+	/*
+	 * Create the result as a TEXT datum, and free working data
+	 */
+	len = buf.len + VARHDRSZ;
+	trigdef = (text *) palloc(len);
+	VARATT_SIZEP(trigdef) = len;
+	memcpy(VARDATA(trigdef), buf.data, buf.len);
+
+	pfree(buf.data);
+
+	ReleaseSysCache(ht_trig);
+	ReleaseSysCache(ht_proc);
+	heap_close(tgrel, AccessShareLock);
+
+	PG_RETURN_TEXT_P(trigdef);
+}
 
 /* ----------
  * get_indexdef			- Get the definition of an index
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 0938ba0b4768e9ac9faf84ff8d816e1747d0f839..835d6f2b5bb8d43ba9b12c7fe635798b46da9739 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.288 2003/03/20 03:34:56 momjian Exp $
+ * $Id: pg_proc.h,v 1.289 2003/03/20 18:58:02 momjian Exp $
  *
  * NOTES
  *	  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"
 DESCR("user name by UID (with fallback)");
 DATA(insert OID = 1643 (  pg_get_indexdef	   PGNSP PGUID 12 f f t f s 1 25 "26"  pg_get_indexdef - _null_ ));
 DESCR("index description");
+DATA(insert OID = 1662 (  pg_get_triggerdef	   PGNSP PGUID 12 f f t f s 1 25 "26"  pg_get_triggerdef - _null_ ));
+DESCR("trigger description");
 DATA(insert OID = 1387 (  pg_get_constraintdef PGNSP PGUID 12 f f t f s 1 25 "26"  pg_get_constraintdef - _null_ ));
 DESCR("constraint description");
 DATA(insert OID = 1716 (  pg_get_expr		   PGNSP PGUID 12 f f t f s 2 25 "25 26"	pg_get_expr - _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index e956f54fef6527c591c4f6cc5f78aa1cfb059539..3a2b20eacbd3c6225f0ceaf4d91827ba2cbab208 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: builtins.h,v 1.208 2003/02/13 05:24:04 momjian Exp $
+ * $Id: builtins.h,v 1.209 2003/03/20 18:58:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -399,6 +399,7 @@ extern Datum pg_get_ruledef(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_viewdef_name(PG_FUNCTION_ARGS);
 extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
+extern Datum pg_get_triggerdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_constraintdef(PG_FUNCTION_ARGS);
 extern Datum pg_get_userbyid(PG_FUNCTION_ARGS);
 extern Datum pg_get_expr(PG_FUNCTION_ARGS);