TG_table_name and TG_table_schema for plpgsql, plus docs and regression.
authorAndrew Dunstan <andrew@dunslane.net>
Sun, 28 May 2006 03:03:17 +0000 (03:03 +0000)
committerAndrew Dunstan <andrew@dunslane.net>
Sun, 28 May 2006 03:03:17 +0000 (03:03 +0000)
doc/src/sgml/plpgsql.sgml
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/pl_exec.c
src/pl/plpgsql/src/plpgsql.h
src/test/regress/expected/triggers.out
src/test/regress/sql/triggers.sql

index 2d1351d9c7e899c748419a09592e26a7167b49f9..4f302a858e7167b61ecbbb35a62d6d34f535e9b1 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.88 2006/03/10 19:10:48 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.89 2006/05/28 03:03:17 adunstan Exp $ -->
 
 <chapter id="plpgsql"> 
   <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -2745,7 +2745,28 @@ RAISE EXCEPTION 'Nonexistent ID --> %', user_id;
      <listitem>
       <para>
        Data type <type>name</type>; the name of the table that caused the trigger
-       invocation.
+       invocation. This is now deprecated, and could disappear in a future 
+      release. Use <literal>TG_TABLE_NAME</> instead.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><varname>TG_TABLE_NAME</varname></term>
+     <listitem>
+      <para>
+       Data type <type>name</type>; the name of the table that 
+      caused the trigger invocation.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><varname>TG_TABLE_SCHEMA</varname></term>
+     <listitem>
+      <para>
+       Data type <type>name</type>; the name of the schema of the 
+      table that caused the trigger invocation.
       </para>
      </listitem>
     </varlistentry>
index 93814db1665c619f486ffd05cf2e80ab1501e089..673ae54ca648af2a7207a13d49bfc2736604a18d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.101 2006/03/14 22:48:23 tgl Exp $
+ *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.102 2006/05/28 03:03:17 adunstan Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -581,6 +581,20 @@ do_compile(FunctionCallInfo fcinfo,
                                         true);
            function->tg_relname_varno = var->dno;
 
+           /* tg_table_name is now preferred to tg_relname */
+           var = plpgsql_build_variable("tg_table_name", 0,
+                                        plpgsql_build_datatype(NAMEOID, -1),
+                                        true);
+           function->tg_table_name_varno = var->dno;
+
+           
+           /* add variable tg_table_schema */
+           var = plpgsql_build_variable("tg_table_schema", 0,
+                                        plpgsql_build_datatype(NAMEOID, -1),
+                                        true);
+           function->tg_table_schema_varno = var->dno;
+
+           
            /* Add the variable tg_nargs */
            var = plpgsql_build_variable("tg_nargs", 0,
                                         plpgsql_build_datatype(INT4OID, -1),
index ee30902dedbe01feae731ca034846f8c74e25fbb..d2ff1fffd52ba64d0a05aa9dc0d41d5af4385501 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.164 2006/04/22 01:26:01 tgl Exp $
+ *   $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.165 2006/05/28 03:03:17 adunstan Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -539,6 +539,21 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
    var->isnull = false;
    var->freeval = true;
 
+   var = (PLpgSQL_var *) (estate.datums[func->tg_table_name_varno]);
+   var->value = DirectFunctionCall1(namein,
+           CStringGetDatum(RelationGetRelationName(trigdata->tg_relation)));
+   var->isnull = false;
+   var->freeval = true;
+
+   var = (PLpgSQL_var *) (estate.datums[func->tg_table_schema_varno]);
+   var->value = DirectFunctionCall1(namein,
+                                    CStringGetDatum(
+                                        get_namespace_name(
+                                            RelationGetNamespace(
+                                                trigdata->tg_relation))));
+   var->isnull = false;
+   var->freeval = true;
+
    var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]);
    var->value = Int16GetDatum(trigdata->tg_trigger->tgnargs);
    var->isnull = false;
index 43b912287b97bc29af21676c8c2ee30cfb13b465..50fe382b323294fcfdfa1854cc6125832758c825 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.69 2006/03/09 21:29:38 momjian Exp $
+ *   $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.70 2006/05/28 03:03:17 adunstan Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -572,6 +572,8 @@ typedef struct PLpgSQL_function
    int         tg_op_varno;
    int         tg_relid_varno;
    int         tg_relname_varno;
+   int         tg_table_name_varno;
+   int         tg_table_schema_varno;
    int         tg_nargs_varno;
 
    int         ndatums;
index e91c5a36320cbb07c8a07cad220af7be70542a21..6d8a436f5001ac0fb09b963ea61ab7627604ed4d 100644 (file)
@@ -386,3 +386,103 @@ select *  from trigtest;
 
 drop table trigtest2;
 drop table trigtest;
+-- dump trigger data
+CREATE TABLE trigger_test (
+        i int,
+        v varchar
+);
+CREATE OR REPLACE FUNCTION trigger_data()  RETURNS trigger 
+LANGUAGE plpgsql AS $$
+
+declare
+
+   argstr text;
+   relid text;
+
+begin
+
+   relid := TG_relid::regclass;
+
+   -- plpgsql can't discover it's trigger data in a hash like perl and python
+   -- can, or by a sort of reflection like tcl can, 
+   -- so we have to hard code the names.
+   raise NOTICE 'TG_NAME: %', TG_name;
+   raise NOTICE 'TG_WHEN: %', TG_when;
+   raise NOTICE 'TG_LEVEL: %', TG_level;
+   raise NOTICE 'TG_OP: %', TG_op;
+   raise NOTICE 'TG_RELID::regclass: %', relid;
+   raise NOTICE 'TG_RELNAME: %', TG_relname;
+   raise NOTICE 'TG_TABLE_NAME: %', TG_table_name;
+   raise NOTICE 'TG_TABLE_SCHEMA: %', TG_table_schema;
+   raise NOTICE 'TG_NARGS: %', TG_nargs;
+
+   argstr := '[';
+   for i in 0 .. TG_nargs - 1 loop
+       if i > 0 then
+           argstr := argstr || ', ';
+       end if;
+       argstr := argstr || TG_argv[i];
+   end loop;
+   argstr := argstr || ']';
+   raise NOTICE 'TG_ARGV: %', argstr;
+
+   if TG_OP != 'INSERT' then
+       raise NOTICE 'OLD: %', OLD;
+   end if;
+
+   if TG_OP != 'DELETE' then
+       raise NOTICE 'NEW: %', NEW;
+   end if;
+   if TG_OP = 'DELETE' then
+       return OLD;
+   else
+       return NEW;
+   end if;
+
+end;
+$$;
+CREATE TRIGGER show_trigger_data_trig 
+BEFORE INSERT OR UPDATE OR DELETE ON trigger_test
+FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
+insert into trigger_test values(1,'insert');
+NOTICE:  TG_NAME: show_trigger_data_trig
+NOTICE:  TG_WHEN: BEFORE
+NOTICE:  TG_LEVEL: ROW
+NOTICE:  TG_OP: INSERT
+NOTICE:  TG_RELID::regclass: trigger_test
+NOTICE:  TG_RELNAME: trigger_test
+NOTICE:  TG_TABLE_NAME: trigger_test
+NOTICE:  TG_TABLE_SCHEMA: public
+NOTICE:  TG_NARGS: 2
+NOTICE:  TG_ARGV: [23, skidoo]
+NOTICE:  NEW: (1,insert)
+update trigger_test set v = 'update' where i = 1;
+NOTICE:  TG_NAME: show_trigger_data_trig
+NOTICE:  TG_WHEN: BEFORE
+NOTICE:  TG_LEVEL: ROW
+NOTICE:  TG_OP: UPDATE
+NOTICE:  TG_RELID::regclass: trigger_test
+NOTICE:  TG_RELNAME: trigger_test
+NOTICE:  TG_TABLE_NAME: trigger_test
+NOTICE:  TG_TABLE_SCHEMA: public
+NOTICE:  TG_NARGS: 2
+NOTICE:  TG_ARGV: [23, skidoo]
+NOTICE:  OLD: (1,insert)
+NOTICE:  NEW: (1,update)
+delete from trigger_test;
+NOTICE:  TG_NAME: show_trigger_data_trig
+NOTICE:  TG_WHEN: BEFORE
+NOTICE:  TG_LEVEL: ROW
+NOTICE:  TG_OP: DELETE
+NOTICE:  TG_RELID::regclass: trigger_test
+NOTICE:  TG_RELNAME: trigger_test
+NOTICE:  TG_TABLE_NAME: trigger_test
+NOTICE:  TG_TABLE_SCHEMA: public
+NOTICE:  TG_NARGS: 2
+NOTICE:  TG_ARGV: [23, skidoo]
+NOTICE:  OLD: (1,update)
+      
+DROP TRIGGER show_trigger_data_trig on trigger_test;
+      
+DROP FUNCTION trigger_data();
+DROP TABLE trigger_test;
index 140b0f2d48523e054044d9707b474161236a2649..fc688a08f9c75720ed9df020b3082d402c393e2c 100644 (file)
@@ -294,3 +294,75 @@ insert into trigtest default values;
 select *  from trigtest;
 drop table trigtest2;
 drop table trigtest;
+
+
+-- dump trigger data
+CREATE TABLE trigger_test (
+        i int,
+        v varchar
+);
+
+CREATE OR REPLACE FUNCTION trigger_data()  RETURNS trigger 
+LANGUAGE plpgsql AS $$
+
+declare
+
+   argstr text;
+   relid text;
+
+begin
+
+   relid := TG_relid::regclass;
+
+   -- plpgsql can't discover it's trigger data in a hash like perl and python
+   -- can, or by a sort of reflection like tcl can, 
+   -- so we have to hard code the names.
+   raise NOTICE 'TG_NAME: %', TG_name;
+   raise NOTICE 'TG_WHEN: %', TG_when;
+   raise NOTICE 'TG_LEVEL: %', TG_level;
+   raise NOTICE 'TG_OP: %', TG_op;
+   raise NOTICE 'TG_RELID::regclass: %', relid;
+   raise NOTICE 'TG_RELNAME: %', TG_relname;
+   raise NOTICE 'TG_TABLE_NAME: %', TG_table_name;
+   raise NOTICE 'TG_TABLE_SCHEMA: %', TG_table_schema;
+   raise NOTICE 'TG_NARGS: %', TG_nargs;
+
+   argstr := '[';
+   for i in 0 .. TG_nargs - 1 loop
+       if i > 0 then
+           argstr := argstr || ', ';
+       end if;
+       argstr := argstr || TG_argv[i];
+   end loop;
+   argstr := argstr || ']';
+   raise NOTICE 'TG_ARGV: %', argstr;
+
+   if TG_OP != 'INSERT' then
+       raise NOTICE 'OLD: %', OLD;
+   end if;
+
+   if TG_OP != 'DELETE' then
+       raise NOTICE 'NEW: %', NEW;
+   end if;
+   if TG_OP = 'DELETE' then
+       return OLD;
+   else
+       return NEW;
+   end if;
+
+end;
+$$;
+
+CREATE TRIGGER show_trigger_data_trig 
+BEFORE INSERT OR UPDATE OR DELETE ON trigger_test
+FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
+
+insert into trigger_test values(1,'insert');
+update trigger_test set v = 'update' where i = 1;
+delete from trigger_test;
+      
+DROP TRIGGER show_trigger_data_trig on trigger_test;
+      
+DROP FUNCTION trigger_data();
+
+DROP TABLE trigger_test;