Обсуждение: BUG #1604: Composite types, triggers, and INET_CLIENT_ADDR() function

Поиск
Список
Период
Сортировка

BUG #1604: Composite types, triggers, and INET_CLIENT_ADDR() function

От
"Chris Trawick"
Дата:
The following bug has been logged online:

Bug reference:      1604
Logged by:          Chris Trawick
Email address:      ctrawick@cultured.net
PostgreSQL version: 8.0.1
Operating system:   i686-pc-linux-gnu, compiled by GCC i686-pc-linux-gnu-gcc
(GCC) 3.3.5  (Gentoo Linux 3.3.5-r1, ssp-3.3.2-3, pie-8.7.7.1)
Description:        Composite types, triggers, and INET_CLIENT_ADDR()
function
Details:

I'm encountering an error when using a plpgsql insert trigger to
automatically log the client connection information using
INET_CLIENT_ADDR().  No changes from default install configuration.  Fresh
PG_DATA install.

Here's my test case:


CREATE TYPE SocketAddress AS(
        addr    INET,
        port    INT
);

CREATE TABLE BugTable(
        intValue        int     NOT NULL,
        clientAddr      SocketAddress   NOT NULL
);

CREATE FUNCTION
        BugTable_setClientAddr()
        RETURNS TRIGGER AS $$
BEGIN
        NEW.clientAddr := (INET_CLIENT_ADDR(),INET_CLIENT_PORT());
        RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER BugTable_onInsert_setClientAddr
        BEFORE INSERT
        ON BugTable
        FOR EACH ROW EXECUTE PROCEDURE BugTable_setClientAddr();


$ psql -h localhost
ctrawick=# SELECT version();
                                                                   version
----------------------------------------------------------------------------
-----------------------------------------------------------------
 PostgreSQL 8.0.1 on i686-pc-linux-gnu, compiled by GCC
i686-pc-linux-gnu-gcc (GCC) 3.3.5  (Gentoo Linux 3.3.5-r1, ssp-3.3.2-3,
pie-8.7.7.1)
(1 row)

ctrawick=# \set VERBOSITY verbose
ctrawick=# INSERT INTO BugTable(intValue) VALUES(0);
ERROR:  XX000: could not find block containing chunk 0x83664e8
CONTEXT:  PL/pgSQL function "bugtable_setclientaddr" line 2 at assignment
LOCATION:  AllocSetFree, aset.c:786

Re: BUG #1604: Composite types, triggers, and INET_CLIENT_ADDR() function

От
Tom Lane
Дата:
"Chris Trawick" <ctrawick@cultured.net> writes:
> I'm encountering an error when using a plpgsql insert trigger to
> automatically log the client connection information using
> INET_CLIENT_ADDR().

Thanks for the clear bug report.  The error is actually generic to any
composite-type operation.  Here's the patch.

            regards, tom lane

Index: rowtypes.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/rowtypes.c,v
retrieving revision 1.8
diff -c -r1.8 rowtypes.c
*** rowtypes.c    31 Dec 2004 22:01:22 -0000    1.8
--- rowtypes.c    18 Apr 2005 17:02:43 -0000
***************
*** 54,59 ****
--- 54,60 ----
  {
      char       *string = PG_GETARG_CSTRING(0);
      Oid            tupType = PG_GETARG_OID(1);
+     HeapTupleHeader result;
      int32        tupTypmod;
      TupleDesc    tupdesc;
      HeapTuple    tuple;
***************
*** 244,254 ****

      tuple = heap_formtuple(tupdesc, values, nulls);

      pfree(buf.data);
      pfree(values);
      pfree(nulls);

!     PG_RETURN_HEAPTUPLEHEADER(tuple->t_data);
  }

  /*
--- 245,264 ----

      tuple = heap_formtuple(tupdesc, values, nulls);

+     /*
+      * We cannot return tuple->t_data because heap_formtuple allocates it
+      * as part of a larger chunk, and our caller may expect to be able to
+      * pfree our result.  So must copy the info into a new palloc chunk.
+      */
+     result = (HeapTupleHeader) palloc(tuple->t_len);
+     memcpy(result, tuple->t_data, tuple->t_len);
+
+     heap_freetuple(tuple);
      pfree(buf.data);
      pfree(values);
      pfree(nulls);

!     PG_RETURN_HEAPTUPLEHEADER(result);
  }

  /*
***************
*** 419,424 ****
--- 429,435 ----
  {
      StringInfo    buf = (StringInfo) PG_GETARG_POINTER(0);
      Oid            tupType = PG_GETARG_OID(1);
+     HeapTupleHeader result;
      int32        tupTypmod;
      TupleDesc    tupdesc;
      HeapTuple    tuple;
***************
*** 580,589 ****

      tuple = heap_formtuple(tupdesc, values, nulls);

      pfree(values);
      pfree(nulls);

!     PG_RETURN_HEAPTUPLEHEADER(tuple->t_data);
  }

  /*
--- 591,609 ----

      tuple = heap_formtuple(tupdesc, values, nulls);

+     /*
+      * We cannot return tuple->t_data because heap_formtuple allocates it
+      * as part of a larger chunk, and our caller may expect to be able to
+      * pfree our result.  So must copy the info into a new palloc chunk.
+      */
+     result = (HeapTupleHeader) palloc(tuple->t_len);
+     memcpy(result, tuple->t_data, tuple->t_len);
+
+     heap_freetuple(tuple);
      pfree(values);
      pfree(nulls);

!     PG_RETURN_HEAPTUPLEHEADER(result);
  }

  /*