trouble creating log table with rules - Mailing list pgsql-sql

From Jim Rowan
Subject trouble creating log table with rules
Date
Msg-id 199906240653.BAA50313@zee.computing.com
Whole thread Raw
List pgsql-sql
I'm trying to create a table (machine_log) that logs changes to another table
(machine).  My goal is to track changes to most of the fields, and to also
track inserts and deletes in the machine table.  I want to know who/when/what
for each change.  I've had some success but not total...

The machine table has a gazillion fields in it (it's a legacy thing; we're
stuck with it for the moment) -- it's certainly not very elegant.  Here are
the tables:

CREATE SEQUENCE "machine_machnum_seq" start 1 increment 1 maxvalue 2147483647 minvalue 1  cache 1 ;
CREATE TABLE "machine" ("host" text NOT NULL,"serial_num_cpu" text,"asset_tag_cpu" text,"risc_tag" text,"dept"
text,"date_purch"date DEFAULT '1/1/0000',"mach_state" text,"owner" text,"cube" text,"mach_user" text,"update_id"
text,"date_added"date DEFAULT text 'now',"date_touched" date DEFAULT text 'now',"date_updated" date DEFAULT text
'now',"notes"text,"po_num" text,"project" text,"asset_type" text,"net_intf" text,"ip_addr" text,"net_num" int2,"e_net"
text,"cpu"text,"os_rev" text,"memory" int2,"swap" float4,"b_systype" text,"hostid" text NOT NULL,"sys_type"
text,"disk_total"int4,"n_cpus" int2,"kernel_id" text,"disk_used" int4,"frame_buff" text,"bkup_status" text,"disk_avail"
int4,"machnum"int4 DEFAULT nextval ( '"machine_machnum_seq"' ) NOT NULL,"y2k" text);
 

CREATE TABLE "machine_log" ("who" text,"date" datetime,"machnum" int4, "col" text,  -- which column in machine was
changed"newval"text); -- and it's new value
 
CREATE UNIQUE INDEX "machine_host_key" on "machine" using btree ( "host" "text_ops" );
CREATE UNIQUE INDEX "machine_machnum_key" on "machine" using btree ( "machnum" "int4_ops" );


I've read the docs in the programmers manual, and can create rules like this:

CREATE RULE "m_log_change" AS ON UPDATE TO "machine"
do ( INSERT INTO machine_log (who, date, machnum, col, newval)   SELECT getpgusername(), 'now'::text, old.machnum,
'host',new.host   WHERE (new.host != old.host) or (old.host IS NOT NULL and new.host IS NULL) or    (old.host IS NULL
andnew.host IS NOT NULL);
 
 INSERT INTO machine_log (who, date, machnum, col, newval)   SELECT getpgusername(), 'now'::text, old.machnum,
'serial_num_cpu',new.serial_num_cpu   WHERE (new.serial_num_cpu != old.serial_num_cpu) or (old.serial_num_cpu IS NOT
NULLand new.serial_num_cpu IS NULL) or    (old.serial_num_cpu IS NULL and new.serial_num_cpu IS NOT NULL);
 
);

So far so good, and this works for any update to these particular fields.
(Side question: why do I have to do the tests to see if one of the values is
null?  If I leave these out, the rule doesn't fire when either old or new is
NULL.)

My big problem is that if I replicate this enough times to cover the fields I 
want, I get this error:

pqReadData() -- backend closed the channel unexpectedly.       This probably means the backend terminated abnormally
  before or while processing the request.
 
We have lost the connection to the backend, so further processing is impossible.  Terminating.


Is there a way I can avoid this error?  Is there a better way to code these
rules? 

(part 2:)
Is there a halfway elegant way to code a rule that will log inserts/deletes?
(I suppose I can name all the fields in machine and the who/when
fields .. is that the only way?)  

I'd rather use SELECT * from machine, but how can I add my extra two fields
that tell me who/when?


Jim Rowan            DCSI            DCE/DFS/Sysadmin Consulting
jmr@computing.com                                            (512) 374-1143


pgsql-sql by date:

Previous
From: Zalman Stern
Date:
Subject: Re: [SQL] Re:Create table doesn't always respect atomicity of transactions
Next
From: Patrick Giagnocavo
Date:
Subject: Best way to support many many users?