There is a bug in check_foreign_key of refint.c which is bundled with
the standard distribution. It occurs when a trigger calling this
function recursively fires another trigger which calls the same
function. The calling check_foreign_key loses its plan informantion and
when it tries to use it the backend closes its channel. You can check it
with the sql script I am attaching below.
The solution to this is to do a find_plan again before executing it at
line 483 of refint.c.
Therefore two more lines should be added before line 483:
sprintf(ident, "%s$%u", trigger->tgname, rel->rd_id);
plan = find_plan(ident, &FPlans, &nFPlans);
before line 483 which is:
ret = SPI_execp(plan->splan[r], kvals, NULL, tcount);
Here is the script to check it:
create table a (
a int4 primary key,
b int4,
c int4,
d int4
);
create table b (
a int4 primary key,
b int4,-- foreign key references a
c int4,
d int4
);
create table ab (
a int4 primary key,
b int4,
c int4,
d int4
);
create table bc (
a int4 primary key,
b int4,
c int4,
d int4
);
create function check_primary_key()
returns opaque
as '/home/bye2data/postgresql-6.3.2/contrib/spi/refint.so'
language 'c';
create function check_foreign_key()
returns opaque
as '/home/bye2data/postgresql-6.3.2/contrib/spi/refint.so'
language 'c';
create trigger t1 before delete or update
on a for each row execute procedure
check_foreign_key(1,'cascade','a','b','b');
create trigger t2 before insert or update
on b for each row execute procedure
check_primary_key('b','a','a');
create trigger t3 before delete or update
on ab for each row execute procedure
check_foreign_key(2,'cascade','a','a','a','bc','a');
create trigger t4 before insert or update
on a for each row execute procedure
check_primary_key('a','ab','a');
create trigger t5 before insert or update
on bc for each row execute procedure
check_primary_key('a','ab','a');
insert into ab values(1,1,1,1);
insert into bc values (1,1,1,1);
insert into a values (1,1,1,1);
delete from ab where a=1;
Sorry for the confusing names of tables and attributes.
- Anand.