Thread: Meta integrity

Meta integrity

From
Renato De Giovanni
Date:
I'm working on a project based on an unusual data model. Some entities
aren't represented by separate tables, they're grouped in the same table
just like the following simplified model shows:

CREATE TABLE class (      id   CHAR(8)     NOT NULL,      name VARCHAR(30) NOT NULL,      PRIMARY KEY (id)
);

INSERT INTO class VALUES ('X', 'Class x') ;
INSERT INTO class VALUES ('Y', 'Class y') ;

CREATE TABLE object (      id       INTEGER NOT NULL,      class_id CHAR(8) NOT NULL,      PRIMARY KEY (id),
FOREIGNKEY (class_id) REFERENCES class (id)
 
);

INSERT INTO object VALUES (1, 'X') ;
INSERT INTO object VALUES (2, 'Y') ;
INSERT INTO object VALUES (3, 'X') ;

Now suppose we need to store in a separate table attributes from objects
from the specific class 'X'. Defining this table with...

CREATE TABLE specific_attribute (      id        INTEGER NOT NULL,      value     TEXT    NOT NULL,      object_id
INTEGERNOT NULL,      PRIMARY KEY (id),      FOREIGN KEY (object_id) REFERENCES object (id)
 
);

...will only guarantee that each attribute points to an existent object
but it will not care about the object's class. Question is: how could I
also enforce this kind of "meta integrity"? The following table
definition came to my mind, but its an illegal construction:

CREATE TABLE specific_attribute (      id        INTEGER NOT NULL,      value     TEXT    NOT NULL,      object_id
INTEGERNOT NULL,      PRIMARY KEY (id),      FOREIGN KEY (object_id, 'X') REFERENCES object (id, class_id)
 
);

Thanks in advance,
--
Renato
Sao Paulo - SP - Brasil
rdg@viafractal.com.br




Re: Meta integrity

From
"Josh Berkus"
Date:
Renato,

> ...will only guarantee that each attribute points to an existent
> object
> but it will not care about the object's class. Question is: how could
> I
> also enforce this kind of "meta integrity"? The following table
> definition came to my mind, but its an illegal construction:
>
> CREATE TABLE specific_attribute (
>        id        INTEGER NOT NULL,
>        value     TEXT    NOT NULL,
>        object_id INTEGER NOT NULL,
>        PRIMARY KEY (id),
>        FOREIGN KEY (object_id, 'X') REFERENCES object (id, class_id)
> );

This is a fairly common problem that has no solution using REFERENCES,
either in Postgres or in SQL 99.  You basically have two choices:

1. The rigorous -- write your own Triggers and Constraints to enforce
this kind of integrity, including INSERT, UPDATE, and DELETE triggers on
the various tables.  Between postgresql.org and Roberto Mello's sight,
there's quite a bit of material on triggers.

2. The simple -- write functions to perform inserts, updates and deletes
on these tables.  Put the relation into those functions, and make users
use those functions instead of direct SQL command access.

I took the second approach to solve a similar problem, because I had
quite a number of other business rules I needed to apply, and adding the
special relationship rule was only one more.

-Josh



______AGLIO DATABASE SOLUTIONS___________________________
                                       Josh Berkus
  Complete information technology      josh@agliodbs.com
   and data management solutions       (415) 565-7293
  for law firms, small businesses        fax 621-2533
    and non-profit organizations.      San Francisco

Attachment

Re: Meta integrity

From
Stephan Szabo
Date:
On Wed, 25 Jul 2001, Renato De Giovanni wrote:

> I'm working on a project based on an unusual data model. Some entities
> aren't represented by separate tables, they're grouped in the same table
> just like the following simplified model shows:
> 
> CREATE TABLE class (
>        id   CHAR(8)     NOT NULL,
>        name VARCHAR(30) NOT NULL,
>        PRIMARY KEY (id)
> );
> 
> INSERT INTO class VALUES ('X', 'Class x') ;
> INSERT INTO class VALUES ('Y', 'Class y') ;
> 
> CREATE TABLE object (
>        id       INTEGER NOT NULL,
>        class_id CHAR(8) NOT NULL,
>        PRIMARY KEY (id),
>        FOREIGN KEY (class_id) REFERENCES class (id)
> );
> 
> INSERT INTO object VALUES (1, 'X') ;
> INSERT INTO object VALUES (2, 'Y') ;
> INSERT INTO object VALUES (3, 'X') ;
> 
> Now suppose we need to store in a separate table attributes from objects
> from the specific class 'X'. Defining this table with...
> 
> CREATE TABLE specific_attribute (
>        id        INTEGER NOT NULL,
>        value     TEXT    NOT NULL,
>        object_id INTEGER NOT NULL,
>        PRIMARY KEY (id),
>        FOREIGN KEY (object_id) REFERENCES object (id)
> );
> 
> ...will only guarantee that each attribute points to an existent object
> but it will not care about the object's class. Question is: how could I
> also enforce this kind of "meta integrity"? The following table
> definition came to my mind, but its an illegal construction:
> 
> CREATE TABLE specific_attribute (
>        id        INTEGER NOT NULL,
>        value     TEXT    NOT NULL,
>        object_id INTEGER NOT NULL,
>        PRIMARY KEY (id),
>        FOREIGN KEY (object_id, 'X') REFERENCES object (id, class_id)
> );

Well, if you don't mind the extra space (and a bit of cheating), this
might work (untested):
add an attribute to specific_attribute class_id default 'X' and a check
constraint to prevent it from ever being something else and a unique
constraint on (id,class_id) to object (meaningless since id is already
unique, but necessary for following the letter of the spec), and then do a
foreign key (object_id, class_id) references object(id, class_id) in
specific_attribute.




Re: Meta integrity

From
"Grigoriy G. Vovk"
Date:
Yes, its not a task for _relation_ dbms.
I am database developer, I like rdbms, but now I think that I should start
to use LDAP for these kind of tasks.
What people can say?

Jul 25, 08:22 -0700, Josh Berkus wrote:

> Renato,
>
> > ...will only guarantee that each attribute points to an existent
> > object
> > but it will not care about the object's class. Question is: how could
> > I
> > also enforce this kind of "meta integrity"? The following table
> > definition came to my mind, but its an illegal construction:
> >
> > CREATE TABLE specific_attribute (
> >        id        INTEGER NOT NULL,
> >        value     TEXT    NOT NULL,
> >        object_id INTEGER NOT NULL,
> >        PRIMARY KEY (id),
> >        FOREIGN KEY (object_id, 'X') REFERENCES object (id, class_id)
> > );
>
> This is a fairly common problem that has no solution using REFERENCES,
> either in Postgres or in SQL 99.  You basically have two choices:
>
> 1. The rigorous -- write your own Triggers and Constraints to enforce
> this kind of integrity, including INSERT, UPDATE, and DELETE triggers on
> the various tables.  Between postgresql.org and Roberto Mello's sight,
> there's quite a bit of material on triggers.
>
> 2. The simple -- write functions to perform inserts, updates and deletes
> on these tables.  Put the relation into those functions, and make users
> use those functions instead of direct SQL command access.
>
> I took the second approach to solve a similar problem, because I had
> quite a number of other business rules I needed to apply, and adding the
> special relationship rule was only one more.
>
> -Josh
>
>
>
> ______AGLIO DATABASE SOLUTIONS___________________________
>                                        Josh Berkus
>   Complete information technology      josh@agliodbs.com
>    and data management solutions       (415) 565-7293
>   for law firms, small businesses        fax 621-2533
>     and non-profit organizations.      San Francisco
>

my best regards,
----------------
Grigoriy G. Vovk



Re: Meta integrity

From
Tom Lane
Date:
Renato De Giovanni <rdg@viafractal.com.br> writes:
>        FOREIGN KEY (object_id, 'X') REFERENCES object (id, class_id)

Why not just store the class_id in the secondary table (if you're
concerned about space, consider using an int4 to represent class_id).
Then you can do a direct two-column foreign key constraint, plus add
a check constraint like CHECK(class_id = 'X').
        regards, tom lane