tg_table_name and tg_table_schema for plpgsql - Mailing list pgsql-patches

From Andrew Dunstan
Subject tg_table_name and tg_table_schema for plpgsql
Date
Msg-id 4478D16C.3030501@dunslane.net
Whole thread Raw
Responses Re: tg_table_name and tg_table_schema for plpgsql
List pgsql-patches
Here's a patch for tg_table_name and tg_table_schema for plpgsql, which
I would appreciate a quick review of just to make sure I haven't missed
something or done something silly. This will complete this exercise - I
have already committed analogous changes for plperl, plpython and pltcl.

cheers

andrew
Index: doc/src/sgml/plpgsql.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/plpgsql.sgml,v
retrieving revision 1.88
diff -c -r1.88 plpgsql.sgml
*** doc/src/sgml/plpgsql.sgml    10 Mar 2006 19:10:48 -0000    1.88
--- doc/src/sgml/plpgsql.sgml    27 May 2006 22:19:28 -0000
***************
*** 2745,2751 ****
       <listitem>
        <para>
         Data type <type>name</type>; the name of the table that caused the trigger
!        invocation.
        </para>
       </listitem>
      </varlistentry>
--- 2745,2772 ----
       <listitem>
        <para>
         Data type <type>name</type>; the name of the table that caused the trigger
!        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: src/pl/plpgsql/src/pl_comp.c
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v
retrieving revision 1.101
diff -c -r1.101 pl_comp.c
*** src/pl/plpgsql/src/pl_comp.c    14 Mar 2006 22:48:23 -0000    1.101
--- src/pl/plpgsql/src/pl_comp.c    27 May 2006 22:19:32 -0000
***************
*** 581,586 ****
--- 581,600 ----
                                           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: src/pl/plpgsql/src/pl_exec.c
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v
retrieving revision 1.164
diff -c -r1.164 pl_exec.c
*** src/pl/plpgsql/src/pl_exec.c    22 Apr 2006 01:26:01 -0000    1.164
--- src/pl/plpgsql/src/pl_exec.c    27 May 2006 22:19:34 -0000
***************
*** 539,544 ****
--- 539,559 ----
      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: src/pl/plpgsql/src/plpgsql.h
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v
retrieving revision 1.69
diff -c -r1.69 plpgsql.h
*** src/pl/plpgsql/src/plpgsql.h    9 Mar 2006 21:29:38 -0000    1.69
--- src/pl/plpgsql/src/plpgsql.h    27 May 2006 22:19:35 -0000
***************
*** 572,577 ****
--- 572,579 ----
      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: src/test/regress/expected/triggers.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/triggers.out,v
retrieving revision 1.20
diff -c -r1.20 triggers.out
*** src/test/regress/expected/triggers.out    27 Feb 2006 16:09:50 -0000    1.20
--- src/test/regress/expected/triggers.out    27 May 2006 22:19:36 -0000
***************
*** 386,388 ****
--- 386,485 ----

  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;
+
+ begin
+
+     -- 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: %', 'bogus:12345';
+     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: bogus:12345
+ 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: bogus:12345
+ 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: bogus:12345
+ 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: src/test/regress/sql/triggers.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/triggers.sql,v
retrieving revision 1.10
diff -c -r1.10 triggers.sql
*** src/test/regress/sql/triggers.sql    27 Feb 2006 16:09:50 -0000    1.10
--- src/test/regress/sql/triggers.sql    27 May 2006 22:19:36 -0000
***************
*** 294,296 ****
--- 294,365 ----
  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;
+
+ begin
+
+     -- 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: %', 'bogus:12345';
+     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;

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: Cleanup for new escape handling
Next
From: Tom Lane
Date:
Subject: Re: tg_table_name and tg_table_schema for plpgsql