]> granicus.if.org Git - postgresql/commitdiff
This patch creates a function named pg_get_triggerdef that takes the oid of
authorBruce Momjian <bruce@momjian.us>
Thu, 20 Mar 2003 18:58:02 +0000 (18:58 +0000)
committerBruce Momjian <bruce@momjian.us>
Thu, 20 Mar 2003 18:58:02 +0000 (18:58 +0000)
a trigger as its parameter.  It is basically copied from the pg_dump
code.

Christopher Kings-Lynne

doc/src/sgml/func.sgml
src/backend/utils/adt/ruleutils.c
src/include/catalog/pg_proc.h
src/include/utils/builtins.h

index 256b0fa3fae42e52e5d5abeab52c250743732b07..27966276d0e14bc4d52542fdc7b5ffadb4f17764 100644 (file)
@@ -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>
index dfed27f89dab7a8ab2d061d02ce35924258237a3..9b34544a3872313561739f6295ea6af9e5b08394 100644 (file)
@@ -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
index 0938ba0b4768e9ac9faf84ff8d816e1747d0f839..835d6f2b5bb8d43ba9b12c7fe635798b46da9739 100644 (file)
@@ -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_ ));
index e956f54fef6527c591c4f6cc5f78aa1cfb059539..3a2b20eacbd3c6225f0ceaf4d91827ba2cbab208 100644 (file)
@@ -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);