plpgsql, fk inherited tables

Started by Nicoover 24 years ago1 messagesgeneral
Jump to latest
#1Nico
nicod@tiscalinet.it

Hi!

I'm trying to get the unique foreign key feature for inherited tables.
There's a problem with plpgsql that I don't understand, could you see
what's wrong?
Comments are well appreciated.

I created a function that given a <name>, tries to return the sequence from
<name>_id_seq

CREATE FUNCTION next_seq_inh_key(text) RETURNS int4 AS '
DECLARE
rec RECORD;
t text;
BEGIN
t := $1 || ''_id_seq'';
SELECT INTO rec nextval( t::text) as id;
RETURN rec.id;
END;
' LANGUAGE 'plpgsql';

This works well when invoked manually from psql.
But from the following function (that is triggered) it doesn't work
properly, it yields the following
ERROR: parser: parse error at or near "$1"

CREATE FUNCTION update_tree() RETURNS OPAQUE AS ' --
DECLARE
sequence int4;
rec RECORD;
treename text;
currtable text;
keytable text;
typetable text;
t text;

BEGIN
treename := TG_ARGV[0];
currtable := TG_RELNAME;
sequence := next_seq_inh_key(treename); -- !!! this is problemful

-- t := treename || ''_id_seq''; -- !!! even this way is problemful
-- sequence := nextval( t::text); -- !!!

keytable := ''inhkeys_'' || treename;
typetable := ''inhtypes_'' || treename;

IF TG_OP = ''INSERT'' THEN
SELECT INTO rec * FROM typetable WHERE "tablename" = currtable;
INSERT INTO keytable ("id", "type") VALUES (sequence, rec.type);
NEW.id := sequence;
RETURN NEW;

ELSEIF TG_OP = ''DELETE'' THEN
DELETE FROM keytable WHERE "id" = OLD.id;

-- ELSEIF TG_OP = ''UPDATE'' --

END IF;

END;
' LANGUAGE 'plpgsql';

=============================================
Here's the complete script that you may use for testing the problem:

CREATE FUNCTION next_seq_inh_key(text) RETURNS int4 AS '
DECLARE
rec RECORD;
-- n int4;
t text;

BEGIN
t := $1 || ''_id_seq'';
SELECT INTO rec nextval( t::text) as id;
RETURN rec.id;
END;
' LANGUAGE 'plpgsql';

CREATE FUNCTION update_tree() RETURNS OPAQUE AS ' --
DECLARE
sequence int4;
rec RECORD;
treename text;
currtable text;
keytable text;
typetable text;
t text;

BEGIN
treename := TG_ARGV[0];
currtable := TG_RELNAME;
-- sequence := next_seq_inh_key(treename);
t := treename || ''_id_seq'';
sequence := nextval( t::text);
keytable := ''inhkeys_'' || treename;
typetable := ''inhtypes_'' || treename;

IF TG_OP = ''INSERT'' THEN
SELECT INTO rec * FROM typetable WHERE "tablename" = currtable;
INSERT INTO keytable ("id", "type") VALUES (sequence, rec.type);
NEW.id := sequence;
RETURN NEW;

ELSEIF TG_OP = ''DELETE'' THEN
DELETE FROM keytable WHERE "id" = OLD.id;

-- ELSEIF TG_OP = ''UPDATE'' -- c

END IF;

END;
' LANGUAGE 'plpgsql';

-------------------------------------------------

CREATE SEQUENCE "people_id_seq" increment 1 minvalue 10000 maxvalue
2147483600 start 10000 cache 1 ;
SELECT * from "people_id_seq";

CREATE TABLE "inhkeys_people" (
"id" int4, -- the unique key across all elements across inherited tables
"type" int2
);
CREATE UNIQUE INDEX inhkeys_uidx_id ON inhkeys_people(id);

CREATE TABLE "inhtypes_people" (
"type" int2,
"tablename" text
);

INSERT INTO "inhtypes_people" (type, tablename)
VALUES (10, 'people');

CREATE TABLE "people" (
"id" int4,
"info" text
);

CREATE TRIGGER people_refkey BEFORE INSERT OR DELETE ON people
FOR EACH ROW EXECUTE PROCEDURE update_tree('people');

ALTER TABLE "people" ADD CONSTRAINT people_fk_inhkeys_people
FOREIGN KEY (id) REFERENCES inhkeys_people(id) INITIALLY DEFERRED;

CREATE UNIQUE INDEX people_uidx_id ON people(id);

INSERT INTO "inhtypes_people" (type, tablename)
VALUES (20, 'student');

CREATE TABLE "student" (
"matr" text
) inherits ("people");

ALTER TABLE "student" ADD CONSTRAINT student_fk_inhkeys_people
FOREIGN KEY (id) REFERENCES inhkeys_people(id) INITIALLY DEFERRED;

CREATE UNIQUE INDEX student_uidx_id ON student(id);

CREATE TRIGGER student_refkey BEFORE INSERT OR DELETE ON student
FOR EACH ROW EXECUTE PROCEDURE update_tree('people');

INSERT INTO student ('info', 'matr') VALUES ('blabla', '333');

Nico