If have some problem with updating `pg_relcheck' entries. Who can help ?

PostgreSQL version:

   CVS of Jan 03 with some additions for my CREATE ERROR TRIGGER project
   (announced on this list). Among those is the following change in
   pg_relcheck:

 	NameData	rcname;
 	text		rcbin;
 	text		rcsrc;
+	int2		rcerrhandlers;/* # of ON ERROR triggers,
+					 * currently on 0 or 1 is supported */
 } FormData_pg_relcheck;
 
   rcerrhandlers is the number of error handlers for a CHECK constraint,
   i.e. the number of procedures to be called if a CHECK constraint fails.
   Error handlers are stored in pg_triggers like normal triggers. They
   reference CHECK constraints by OID in the same way as normal triggers
   reference relations by OID. For this to work I have still to add an OID
   to pg_relcheck, but the current question does not depend on this.

Error handlers are created by the following statement:

=# create table mytab (arg text CHECK (length(arg)>10));
CREATE
=# CREATE ERROR TRIGGER ehtest on CONSTRAINT CHECK mytab_arg FOR EACH ROW EXECUTE PROCEDURE __proc('arg');
CREATE

In executing the CREATE ERROR TRIGGER command I have to update the entry
of the CHECK constraint in pg_relcheck and ro add an entry to pg_trigger.
The problem I have is related to updating the pg_relcheck entry.

For this I use the following code:

	/* Grab an exclusive lock on the pg_relcheck relation */
	rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);

	/*
	 * Create the scan key. We  need to match the name of the CHECK
	 * constraint.
	 */
	ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcname,
			       F_NAMEEQ, PointerGetDatum(constrName));
	/*
	 * Begin scanning the heap
	 */
	rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);

	/*
	 * We take the first CHECK constraint we can find.
	 */

	if (! HeapTupleIsValid(rctup = heap_getnext(rcscan, 0)))
	{
	  elog(ERROR,"CreateErrorHandler: CHECK constraint \"%s\" does not exist",
	       constrName);
	}

	/**
	 *  Copy the tuple to be able to end the scan.
	 */
	rctup = heap_copytuple(rctup);

	heap_endscan(rcscan);

[snip]

	/**
	 *  update the error handler counter of the constraint
	 */
	((Form_pg_relcheck) GETSTRUCT(rctup))->rcerrhandlers = found + 1;
	simple_heap_update(rcrel, &rctup->t_self, rctup);
				
	/**
	 * update the indices, too
	 */
[snip]
	heap_freetuple(rctup);

	heap_close(rcrel, RowExclusiveLock);


pg_relcheck before the update is done:

# select * from pg_relcheck where rcname='mytab_arg';
rcrelid |  rcname   | rcbin ..  | rcsrc .. | rcerrhandlers
  16570 | mytab_arg | ({ EXPR :typeOid 16  :opType op :oper { OPER :opno 521 :opid 147 :opresulttype 16 } :args ({ EXPR :typeOid 23  :opType func :oper { FUNC :funcid 1317 :functype 23 } :args ({ VAR :varno 1 :varattno 1 :vartype 25 :vartypmod -1  :varlevelsup 0 :varnoold 1 :varoattno 1})} { CONST :consttype 23 :constlen 4 :constbyval true :constisnull false :constvalue  4 [ 10 0 0 0 ] })}) | (length(arg) > 10) |             0
(1 row)

pg_relcheck after the update is done:

=# select * from pg_relcheck where rcname='mytab_arg';
 rcrelid |  rcname   |     rcbin     |       rcsrc        | rcerrhandlers 
---------+-----------+---------------+--------------------+---------------
   16564 | mytab_arg | ({ EXPR :typ | (length(arg) > 10) |             0
(1 row)

Furthermore when I abort the transaction (with `elog') after the code
segment shown above is executed, the entry in pg_relcheck even vanishes !

I'm really puzzled.

-- 
Holger Krug
hkrug@rationalizer.com

Fri, 11 Jan 2002 11:52:39 +0100
Holger Krug <hkrug@rationalizer.com>
Problems with simple_heap_update and Form_pg_relcheck
On Fri, Jan 11, 2002 at 11:52:39AM +0100, Holger Krug wrote:
> Furthermore when I abort the transaction (with `elog') after the code
> segment shown above is executed, the entry in pg_relcheck even vanishes !

This remark applies to a slightly different version of the code, when
I do not heap_copytuple but modify the value in place. OK, that's
understandable, so please forget it. But the problem, that
`rcerrhandlers' is not updated, remains.

-- 
Holger Krug
hkrug@rationalizer.com

Fri, 11 Jan 2002 11:59:34 +0100
Holger Krug <hkrug@rationalizer.com>
Re: Problems with simple_heap_update and Form_pg_relcheck
Holger Krug <hkrug@rationalizer.com> writes:
> 	((Form_pg_relcheck) GETSTRUCT(rctup))->rcerrhandlers = found + 1;

What's an "rcerrhandlers"?  It doesn't appear in current sources.

> pg_relcheck after the update is done:
> [rcbin is messed up]

I have a feeling you added rcerrhandlers after the variable-length
fields.  Not good, at least not if you want to access it via a C
struct.  See, eg,
http://developer.postgresql.org/cvsweb.cgi/pgsql/src/backend/catalog/README

			regards, tom lane

Fri, 11 Jan 2002 11:57:27 -0500
Tom Lane <tgl@sss.pgh.pa.us>
Re: Problems with simple_heap_update and Form_pg_relcheck 
On Fri, Jan 11, 2002 at 11:57:27AM -0500, Tom Lane wrote:
> Holger Krug <hkrug@rationalizer.com> writes:
> > 	((Form_pg_relcheck) GETSTRUCT(rctup))->rcerrhandlers = found + 1;
> 
> What's an "rcerrhandlers"?  It doesn't appear in current sources.

Yes, it's part of my project to add error handlers. It's the number
of error handlers for this constraint, currently my code allows
as values either 0 or 1.

> I have a feeling you added rcerrhandlers after the variable-length
> fields.  Not good, at least not if you want to access it via a C
> struct.  See, eg,
> http://developer.postgresql.org/cvsweb.cgi/pgsql/src/backend/catalog/README

I have that feeling, too. Thanks for the prompt help. 

-- 
Holger Krug
hkrug@rationalizer.com

Fri, 11 Jan 2002 18:39:49 +0100
Holger Krug <hkrug@rationalizer.com>
Re: Problems with simple_heap_update and Form_pg_relcheck