postgresql dungeon with table inheritance and constraints edel sherratt
TRANSCRIPT
![Page 1: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/1.jpg)
POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS
Edel Sherratt
![Page 2: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/2.jpg)
Relations• location{ name, description, is_lit }
• exit{ name, description, is_open, exits_from, leads_to }
• exit_pair{name_1, exits_from_1, name_2, exits_from_2}
• item{ name, description, kind, is_lit, is_at, held_by }
• character{ name, description, kind, location }
• Nowhere location: (nowhere, ' ', false)
• Self character: (me, myself, person, my location);
• Nobody character: (nobody, ' ', nonentity, nowhere)
![Page 3: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/3.jpg)
Location
• create table location (name varchar(20) primary key,description text,is_lit boolean );
• insert into location (name, description, is_lit) values ('nowhere', ' ', false);
![Page 4: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/4.jpg)
Exit
• create table exit (name varchar(20),description text,is_open boolean,exits_from varchar(20) references location(name),leads_to varchar(20) references location(name),primary key(exits_from, name) );
![Page 5: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/5.jpg)
Character with Table Inheritance• create table character (
name varchar(20) primary key,description text,location varchar(20) references location(name));
• create table monster () inherits (character);• create table player () inherits (character);
![Page 6: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/6.jpg)
Problems• Primary and foreign key constraints are not inherited
(hopefully will be in future PostgreSQL releases)• Work round this using functions and triggers
![Page 7: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/7.jpg)
Primary key: Character and descendants
• /* character.name is a primary key; pkey_character_name checks the inheritance hierarcy from character to ensure that name is unique and not null */
• create function pkey_character_name() returns trigger as $pkey_character_name$BEGIN
if (exists (select * from character where character.name = NEW.name))
then raise exception ‘cannot have more than one character named %.', NEW.name;
end if;return NEW;
END$pkey_character_name$ language plpgsql;
![Page 8: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/8.jpg)
Triggering the not null and unique checks on monster.name
• create table monster () inherits (character);• create trigger pkey_character_name
before insert on monsterfor each row
execute procedure pkey_character_name();• The same is needed for other descendants of character
(such as player)
![Page 9: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/9.jpg)
Foreign key reference to location: character and descendants• create function valid_location() returns trigger as
$valid_location$BEGIN
if not exists(select name from location where location.name = NEW.location)
then raise exception'There is no location called %', NEW.location;end if;return NEW;
END $valid_location$ language plpgsql;
![Page 10: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/10.jpg)
Triggering the referential integrity constraint on character.location
• create trigger valid_locationbefore insert on monsterfor each row execute procedure valid_location();
• The same is done for player• And the same for item, which also refers to location.name• And for the descendants of item
![Page 11: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/11.jpg)
Item with table inheritance• create table item (
name varchar (20) not null,description text,location varchar (20)
references location(name));• create table portable_item (
held_by varchar (20)) inherits (item);
![Page 12: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/12.jpg)
More descendants of item• create table light_source (is_lit boolean) inherits (item);• create table portable_light_source ()
inherits (portable_item, light_source);• And each of these has triggers to enforce entity and
referential integrity constraints.
![Page 13: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/13.jpg)
A domain-specific constraint• /* The location of a portable item is the same as the location
of its holder. When a new portable item is added to the database, its location is set to the location of its holder. */
• create function no_bilocation () returns trigger as $no_bilocation$BEGIN
if (NEW.held_by != 'nobody‘ thenNEW.location :=
(select location from character where character.name = NEW.held_by);
end if;return NEW;
END $no_bilocation$ language plpgsql;
![Page 14: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/14.jpg)
Triggering ‘no_bilocation’
• create trigger no_bilocation
before insert on portable_item
for each row
execute procedure no_bilocation();
• create trigger no_bilocation
before insert on portable_light_source
for each row
execute procedure no_bilocation();
![Page 15: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/15.jpg)
Another domain-specific constraint• /* when a character changes location, all the portable
items held by that character should move as well. */• create function move_portable_items ()
returns trigger as $move_portable_items$BEGIN
update portable_itemset location = NEW.locationwhere portable_item.held_by = NEW.name;
return NEW;END$move_portable_items$ language plpgsql;
![Page 16: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/16.jpg)
Triggering ‘move_portable_items’
• create trigger move_portable_items after update on character
for each rowexecute procedure move_portable_items();
![Page 17: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/17.jpg)
Yet another domain-specific constraint
• /* no_remote_pickup ensures that the held_by attribute of a portable item can only be updated to the name of a holder whose location is the same as that of the item; in other words, a character must move to the place where an item is before picking up the item. */
• create function no_remote_pickup() returns trigger as $no_remote_pickup$BEGIN
if NEW.location !=(select location from character where character.name = NEW.held_by)
then raise exception '% must move to % in order to pick up %',NEW.held_by, NEW.location, NEW.name;
end if;return NEW;
END $no_remote_pickup$ language plpgsql;
![Page 18: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/18.jpg)
Table Inheritance• Convenient, but with some problems
• Check constraints and not null constraints are inherited, but other kinds of constraints are not
• Unique, Primary key and foreign key constraints are not inherited
• Some SQL commands default to accessing descendants; others do not
• Commands that default to accessing descendants use ONLY to avoid doing so
![Page 19: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/19.jpg)
User defined composite types• PostgreSQL also enables user defined composite types• Composite types allow table elements to contain
structured data• Composite types are a kind of user defined type like those
discussed in connection with object-relational database management systems.
![Page 20: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/20.jpg)
Functions and Triggers• Primary use: to implement domain-specific constraints at
the database level• Also used to work round lack of constraint inheritance in
this example• Typically:
• Define a function that returns a named trigger• Then add that trigger to one or more tables
![Page 21: POSTGRESQL DUNGEON WITH TABLE INHERITANCE AND CONSTRAINTS Edel Sherratt](https://reader035.vdocuments.mx/reader035/viewer/2022070306/5519b3f55503467a578b4708/html5/thumbnails/21.jpg)
Conclusion• Modern relational database management systems provide
various extras• But it is important to weigh up the benefits of these
against their costs