Re: integrity and inherit - Mailing list pgsql-novice

From Oliver Elphick
Subject Re: integrity and inherit
Date
Msg-id 200108231324.f7NDOIoa017203@linda.lfix.co.uk
Whole thread Raw
In response to Re: integrity and inherit  (Bo Lorentsen <bl@netgroup.dk>)
List pgsql-novice
Bo Lorentsen wrote:
  >Oliver Elphick wrote:
  >> Referential integrity doesn't support references to inheritance hierarchie
      >s.
  >> You will have to redesign your database.
  >
  >That is sad news, is this scheduled to be fixed in the near future ?

It's in the TODO list...

  >> For example, have a trigger on each table in the hierarchy to update a
  >> table of keys and use RI on that; it would also help you to maintain
  >> primary keys -- you probably think that table derived inherits the
  >> primary key constraint from base, but it doesn't.  That is another problem
  >> with the current implementation of inheritance. :-(
  >
  >I'm not quite sure what you meen. Does this mean that I sould make a rule on
  >insert on every enherited table, that makes sure the base is updated ?

There's an example below.  resources is the ancestor and has four
descendants, all at the same level.  A resource key must occur only
once in the whole hierarchy and needs to be available for RI. resource
is a deferred class; that is, every resource must be a member of one of
the four descendant classes, so resource itself should have no rows.

  >When I do my "SELECT * FROM base" and see the value id the ID, what kind of
  >value am I then looking at ?

You are seeing all the records from the hierarchy of base and all its
descendants; that part of inheritance works; but RI does not work (yet).


Example (see above):

-- Index of resources

CREATE TABLE resource_list (
       id    VARCHAR(4)    PRIMARY KEY,
       flag  CHAR(1)       NOT NULL
                           CONSTRAINT "valid flag"
                              CHECK (flag in ('B', 'M', 'L', 'T')),
       name  TEXT          NOT NULL UNIQUE
)
;


CREATE TABLE resource
(
   id        VARCHAR(4),
   ...
,
PRIMARY KEY (id),
CONSTRAINT "resource in resource_list"
   FOREIGN KEY (id) REFERENCES resource_list (id)
      ON UPDATE CASCADE
      ON DELETE RESTRICT
      DEFERRABLE

);


CREATE FUNCTION update_resource_list()
  RETURNS opaque
  AS '
     -- update resource_list when a resource is added or deleted
     DECLARE
        flag     CHAR(1);
        cnt      INTEGER := 0;
        listrec  RECORD;
     BEGIN
        IF TG_OP = ''DELETE'' THEN
           DELETE FROM resource_list WHERE resource = OLD.id;
        ELSE
           IF TG_RELNAME = ''tool'' THEN
              flag := ''T'';
           ELSIF TG_RELNAME = ''bench'' THEN
              flag := ''B'';
           ELSIF TG_RELNAME = ''machine'' THEN
              flag := ''M'';
           ELSIF TG_RELNAME = ''labour'' THEN
              flag := ''L'';
           ELSE
              RAISE ERROR ''resource_def() function called on unexpected table
%'', TG_RELNAME;
           END IF;
           FOR listrec IN EXECUTE ''SELECT * FROM resource_list WHERE id = ''
|| quote_literal(OLD.id) LOOP
              cnt := cnt + 1
              IF flag != listrec.flag OR id != OLD.id THEN
                 EXECUTE ''UPDATE resource_list SET id = '' ||
quote_literal(NEW.id) || '', flag = '' || quote_literal(flag) || '' WHERE id =
'' || quote_literal (OLD.id);
              END IF;
           END LOOP;
           IF cnt = 0 THEN
              EXECUTE ''INSERT INTO resource_list VALUES ('' ||
                 quote_literal(NEW.id) || '', '' ||
                 quote_literal(flag);
           END IF;
        END IF;
     END;
  ' LANGUAGE 'plpgsql';

-- resource is a deferred class; it cannot have any rows itself
CREATE RULE no_resource AS ON INSERT
       TO resource
       DO INSTEAD NOTHING;


CREATE TABLE labour
(
   pay          NUMERIC(12,2)   NOT NULL
                                CHECK (pay >= 0),
   ...
,
PRIMARY KEY (id),
CONSTRAINT "resource in resource_list"
   FOREIGN KEY (id) REFERENCES resource_list (id)
      ON UPDATE CASCADE
      ON DELETE RESTRICT
      DEFERRABLE

)
inherits (resource)
;


CREATE TRIGGER on_labour_change BEFORE INSERT OR UPDATE
       ON labour FOR EACH ROW
       EXECUTE PROCEDURE update_resource_list();


CREATE TABLE bench
(
   descr     TEXT,
   ...
,
PRIMARY KEY (id),
CONSTRAINT "resource in resource_list"
   FOREIGN KEY (id) REFERENCES resource_list (id)
      ON UPDATE CASCADE
      ON DELETE RESTRICT
      DEFERRABLE

)
   INHERITS (resource)
;


CREATE TRIGGER on_bench_change BEFORE INSERT OR UPDATE
       ON bench FOR EACH ROW
       EXECUTE PROCEDURE update_resource_list();


CREATE TABLE machine
(
   descrip      TEXT            NOT NULL,
  ...
,
PRIMARY KEY (id),
CONSTRAINT "resource in resource_list"
   FOREIGN KEY (id) REFERENCES resource_list (id)
      ON UPDATE CASCADE
      ON DELETE RESTRICT
      DEFERRABLE

)
   INHERITS (resource)
;


CREATE TRIGGER on_machineT_change BEFORE INSERT OR UPDATE
       ON machine FOR EACH ROW
       EXECUTE PROCEDURE update_resource_list();


CREATE TABLE tool
(
   maker       TEXT           NOT NULL,
  ...
,
PRIMARY KEY (id),
CONSTRAINT "resource in resource_list"
   FOREIGN KEY (id) REFERENCES resource_list (id)
      ON UPDATE CASCADE
      ON DELETE RESTRICT
      DEFERRABLE

)
INHERITS (resource)
;


CREATE TRIGGER on_tool_change BEFORE INSERT OR UPDATE
       ON tool FOR EACH ROW
       EXECUTE PROCEDURE update_resource_list();




--
Oliver Elphick                                Oliver.Elphick@lfix.co.uk
Isle of Wight                              http://www.lfix.co.uk/oliver
PGP: 1024R/32B8FAA1: 97 EA 1D 47 72 3F 28 47  6B 7E 39 CC 56 E4 C1 47
GPG: 1024D/3E1D0C1C: CA12 09E0 E8D5 8870 5839  932A 614D 4C34 3E1D 0C1C
                 ========================================
     "For God hath not appointed us to wrath, but to obtain
      salvation by our Lord Jesus Christ, Who died for us,
      that, whether we wake or sleep, we should live
      together with him."
                         I Thessalonians 5:9,10



pgsql-novice by date:

Previous
From: "Oliver Elphick"
Date:
Subject: Re: protected ON DELETE CASCADE
Next
From: "Albert REINER"
Date:
Subject: Re: Bad timestamp external representation