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

Started by Chris Trawickabout 21 years ago2 messagesbugs
Jump to latest
#1Chris Trawick
ctrawick@cultured.net

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

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chris Trawick (#1)
Re: BUG #1604: Composite types, triggers, and INET_CLIENT_ADDR() function

"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);
}

/*