begin; /* ┌─────────────────┐ │ host │ ├─────────────────┤ │ public_id (pk) │ │ catalog_id (fk) │ │ │ └─────────────────┘ ╲│╱ ○ │ ┼ ┼ ┌─────────────────┐ ┌─────────────────┐ │ iam_scope │ │ host_catalog │ ├─────────────────┤ ├─────────────────┤ │ public_id (pk) │ ╱│ public_id (pk) │ │ │┼┼──────○─│ scope_id (fk) │ │ │ ╲│ │ └─────────────────┘ └─────────────────┘ ┼ ┼ │ ○ ╱│╲ ┌─────────────────┐ │ host_set │ ├─────────────────┤ │ public_id (pk) │ │ catalog_id (fk) │ │ │ └─────────────────┘ */ -- host_catalog create table host_catalog ( public_id wt_public_id primary key, scope_id wt_scope_id not null references iam_scope (public_id) on delete cascade on update cascade, -- The order of columns is important for performance. See: -- https://dba.stackexchange.com/questions/58970/enforcing-constraints-two-tables-away/58972#58972 -- https://dba.stackexchange.com/questions/27481/is-a-composite-index-also-good-for-queries-on-the-first-field unique(scope_id, public_id) ); create trigger immutable_columns before update on host_catalog for each row execute procedure immutable_columns('public_id', 'scope_id'); -- insert_host_catalog_subtype() is a before insert trigger -- function for subtypes of host_catalog create or replace function insert_host_catalog_subtype() returns trigger as $$ begin insert into host_catalog (public_id, scope_id) values (new.public_id, new.scope_id); return new; end; $$ language plpgsql; -- delete_host_catalog_subtype() is an after delete trigger -- function for subtypes of host_catalog create or replace function delete_host_catalog_subtype() returns trigger as $$ begin delete from host_catalog where public_id = old.public_id; return null; -- result is ignored since this is an after trigger end; $$ language plpgsql; -- host create table host ( public_id wt_public_id primary key, catalog_id wt_public_id not null references host_catalog (public_id) on delete cascade on update cascade, unique(catalog_id, public_id) ); create trigger immutable_columns before update on host for each row execute procedure immutable_columns('public_id', 'catalog_id'); -- insert_host_subtype() is a before insert trigger -- function for subtypes of host create or replace function insert_host_subtype() returns trigger as $$ begin insert into host (public_id, catalog_id) values (new.public_id, new.catalog_id); return new; end; $$ language plpgsql; -- delete_host_subtype() is an after delete trigger -- function for subtypes of host create or replace function delete_host_subtype() returns trigger as $$ begin delete from host where public_id = old.public_id; return null; -- result is ignored since this is an after trigger end; $$ language plpgsql; -- host_set create table host_set ( public_id wt_public_id primary key, catalog_id wt_public_id not null references host_catalog (public_id) on delete cascade on update cascade, unique(catalog_id, public_id) ); create trigger immutable_columns before update on host_set for each row execute procedure immutable_columns('public_id', 'catalog_id'); -- insert_host_set_subtype() is a before insert trigger -- function for subtypes of host_set create or replace function insert_host_set_subtype() returns trigger as $$ begin insert into host_set (public_id, catalog_id) values (new.public_id, new.catalog_id); return new; end; $$ language plpgsql; -- delete_host_set_subtype() is an after delete trigger -- function for subtypes of host_set create or replace function delete_host_set_subtype() returns trigger as $$ begin delete from host_set where public_id = old.public_id; return null; -- result is ignored since this is an after trigger end; $$ language plpgsql; insert into oplog_ticket (name, version) values ('host_catalog', 1), ('host', 1), ('host_set', 1); commit;