plpgsql, fk inherited tables

From: Nico <nicod(at)tiscalinet(dot)it>
To: pgsql-general(at)postgresql(dot)org
Subject: plpgsql, fk inherited tables
Date: 2001-09-05 08:38:00
Message-ID: 9n4h42$1tnf$1@news.tht.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

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

Browse pgsql-general by date

  From Date Subject
Next Message Martijn van Oosterhout 2001-09-05 10:06:17 Re: many junction tables
Previous Message Arne Weiner 2001-09-05 08:26:11 Re: many junction tables