From: <pau...@us...>
<pau...@us...> - 2009-01-23 15:11:51
|
Hello anyone who's there, Here's a proposed SQL schema for Everydevel. It's aims are to make nodes more light-weight and make it easier for the platform to be extended. It's postgresql because I knew that using views and rules I could make it transparent to the current code, I'm not sure that mysql and sqlite would allow this flexibility. Other points: Yes it's slow, especially packing and unpacking those permissions, but a new front end model will fix that. Yes, it's complicated, but higher levels of normalisation always involve more tables. Constructive thoughts? Paul CREATE TABLE "node_relation_type" ( name varchar(125) UNIQUE NOT NULL, description text, node_relation_type_pk serial, PRIMARY KEY ( "node_relation_type_pk" ) ) ; CREATE INDEX index_node_relation_type ON node_relation_type ( name ) ; CREATE AGGREGATE textcat_all( basetype = text, sfunc = textcat, stype = text, initcond = '' ); CREATE TABLE "node_basic" ( node_id bigserial UNIQUE NOT NULL, type_nodetype bigint, createtime timestamp NOT NULL, PRIMARY KEY (node_id) ); CREATE TABLE "node_relationship" ( node bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, hasa_node bigint REFERENCES node_basic(node_id) ON DELETE RESTRICT, relation_type int REFERENCES node_relation_type( node_relation_type_pk) ON DELETE RESTRICT, PRIMARY KEY ("node", "hasa_node", "relation_type") ) ; CREATE TABLE "sqltable_type" ( sqltable_type varchar(255) NOT NULL, description varchar(255), sqltable_type_pk serial, PRIMARY KEY ( "sqltable_type_pk" ) ) ; CREATE TABLE "sqltable" ( sqltable_name varchar(255) NOT NULL UNIQUE, type int REFERENCES sqltable_type(sqltable_type_pk) ON DELETE RESTRICT, sqltable_pk bigserial NOT NULL, PRIMARY KEY ( sqltable_pk ) ) ; CREATE TABLE "node_sqltable" ( sqltable bigint REFERENCES sqltable(sqltable_pk), nodetype_id bigint REFERENCES node_basic(node_id), node_sqltable_pk serial NOT NULL, UNIQUE (sqltable, nodetype_id), PRIMARY KEY ( node_sqltable_pk ) ) ; CREATE TABLE "nodegroup_restrict_type"( group_nodetype_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, only_nodetype bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY( group_nodetype_id, only_nodetype ) ) ; CREATE TABLE "nodebase_restrictdupes" ( nodetype_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (nodetype_id) ) ; CREATE TABLE "nodebase_node_workspace" ( node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, enable boolean NOT NULL, PRIMARY KEY (node_id) ) ; CREATE TABLE "nodebase_node_revisions" ( node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, maxrevisions int DEFAULT 0 NOT NULL, PRIMARY KEY (node_id) ) ; CREATE TABLE "node_modified" ( modified timestamp, node_id bigint NOT NULL REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (node_id) ) ; CREATE TABLE "node_title" ( title varchar(240), node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (node_id) ) ; CREATE TABLE "node_statistics_hits" ( hits bigint NOT NULL DEFAULT 0, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (node_id) ) ; CREATE TABLE "node_location" ( loc_location bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (node_id) ) ; CREATE TABLE "node_statistics_reputation" ( reputation bigint NOT NULL DEFAULT 0, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (node_id) ) ; CREATE TABLE "node_lock" ( locktime timestamp NOT NULL, lockby_user bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (node_id) ) ; CREATE TABLE "user_type" ( user_type_pk serial NOT NULL, usertype varchar(32) NOT NULL, description varchar(255), PRIMARY KEY ("user_type_pk") ) ; CREATE TABLE "permission_type" ( permission_type_pk serial NOT NULL, permission varchar(127) NOT NULL, description varchar(255), PRIMARY KEY("permission_type_pk") ) ; CREATE TABLE "permission_behaviour" ( permission_behaviour_pk serial NOT NULL, behaviour varchar(10) NOT NULL, description varchar(255), PRIMARY KEY ("permission_behaviour_pk") ) ; CREATE TABLE "node_authorisation" ( permission_type int REFERENCES permission_type(permission_type_pk) ON DELETE RESTRICT NOT NULL, permission_behaviour int REFERENCES permission_behaviour(permission_behaviour_pk) ON DELETE RESTRICT NOT NULL, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (permission_type, node_id, permission_behaviour) ) ; CREATE TABLE "node_access" ( user_type int REFERENCES user_type(user_type_pk) ON DELETE RESTRICT NOT NULL, permission_type int REFERENCES permission_type(permission_type_pk) ON DELETE RESTRICT NOT NULL, permission_behaviour int REFERENCES permission_behaviour(permission_behaviour_pk) ON DELETE RESTRICT NOT NULL, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (user_type, permission_type, node_id, permission_behaviour) ) ; CREATE TABLE "node_dynamicpermission" ( type int REFERENCES user_type (user_type_pk) ON DELETE RESTRICT, permission bigint REFERENCES node_basic(node_id) ON DELETE RESTRICT, node_id bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, PRIMARY KEY (type, node_id) ) ; CREATE TABLE "node_relationship_usertype" ( node bigint REFERENCES node_basic(node_id) ON DELETE CASCADE, with_node bigint REFERENCES node_basic(node_id) ON DELETE RESTRICT, relation_type int REFERENCES node_relation_type( node_relation_type_pk) ON DELETE RESTRICT, user_type int REFERENCES user_type(user_type_pk) ON DELETE RESTRICT, PRIMARY KEY ("node", "with_node", "relation_type", "user_type") ) ; CREATE FUNCTION dynamicpermission ( bigint, text ) RETURNS bigint AS $$ SELECT permission FROM node_dynamicpermission WHERE type = ( SELECT user_type.user_type_pk FROM user_type WHERE user_type.usertype = $2) AND node_id = $1; $$ LANGUAGE SQL; ; CREATE OR REPLACE FUNCTION nodepermissions(bigint, varchar) RETURNS text AS $$ SELECT CASE ( SELECT permission_behaviour.behaviour from node_access, user_type, permission_type, permission_behaviour where permission_type.permission = 'read' AND node_access.node_id = $1 AND user_type.usertype = $2 AND node_access.user_type = user_type.user_type_pk AND node_access.permission_behaviour = permission_behaviour.permission_behaviour_pk AND node_access.permission_type = permission_type.permission_type_pk) WHEN 'enable' THEN 'r' WHEN 'disable' THEN '-' WHEN 'inherit' THEN 'i' END || CASE ( SELECT permission_behaviour.behaviour from node_access, user_type, permission_type, permission_behaviour where permission_type.permission = 'write' AND node_access.node_id = $1 AND user_type.usertype = $2 AND node_access.user_type = user_type.user_type_pk AND node_access.permission_behaviour = permission_behaviour.permission_behaviour_pk AND node_access.permission_type = permission_type.permission_type_pk) WHEN 'enable' THEN 'w' WHEN 'disable' THEN '-' WHEN 'inherit' THEN 'i' END || CASE ( SELECT permission_behaviour.behaviour from node_access, user_type, permission_type, permission_behaviour where permission_type.permission = 'execute' AND node_access.node_id = $1 AND user_type.usertype = $2 AND node_access.user_type = user_type.user_type_pk AND node_access.permission_behaviour = permission_behaviour.permission_behaviour_pk AND node_access.permission_type = permission_type.permission_type_pk) WHEN 'enable' THEN 'x' WHEN 'disable' THEN '-' WHEN 'inherit' THEN 'i' END || CASE ( SELECT permission_behaviour.behaviour from node_access, user_type, permission_type, permission_behaviour where permission_type.permission = 'delete' AND node_access.node_id = $1 AND user_type.usertype = $2 AND node_access.user_type = user_type.user_type_pk AND node_access.permission_behaviour = permission_behaviour.permission_behaviour_pk AND node_access.permission_type = permission_type.permission_type_pk) WHEN 'enable' THEN 'd' WHEN 'disable' THEN '-' WHEN 'inherit' THEN 'i' END || CASE WHEN $2 = 'author' OR $2 = 'defaultauthor' THEN '' ELSE ( CASE ( SELECT permission_behaviour.behaviour from node_access, user_type, permission_type, permission_behaviour where permission_type.permission = 'create' AND node_access.node_id = $1 AND user_type.usertype = $2 AND node_access.user_type = user_type.user_type_pk AND node_access.permission_behaviour = permission_behaviour.permission_behaviour_pk AND node_access.permission_type = permission_type.permission_type_pk) WHEN 'enable' THEN 'c' WHEN 'disable' THEN '-' WHEN 'inherit' THEN 'i' END) END; $$ LANGUAGE SQL; ; CREATE FUNCTION "related_node_id" ( bigint, varchar ) RETURNS bigint AS $$ SELECT node_relationship.hasa_node FROM node_relationship, node_relation_type WHERE node_relationship.node = $1 AND node_relationship.relation_type = node_relation_type_pk AND node_relation_type.name = $2 $$ LANGUAGE SQL; ; CREATE TABLE "attribute_type" ( name varchar(125) UNIQUE NOT NULL, description varchar(255), attribute_type_pk serial, PRIMARY KEY ("attribute_type_pk") ) ; CREATE TABLE "timestamp_attribute" ( time timestamp NOT NULL, node bigint REFERENCES node_basic( node_id) ON DELETE CASCADE, PRIMARY KEY ("node") ) ; CREATE VIEW "node" AS SELECT node_basic.node_id AS node_id, node_basic.type_nodetype, node_basic.createtime, related_node_id( node_basic.node_id, 'author_user') AS author_user, node_title.title, node_modified.modified, node_statistics_hits.hits, related_node_id( node_basic.node_id, 'loc_location') AS loc_location, node_statistics_reputation.reputation, node_lock.locktime, node_lock.lockby_user, nodepermissions( node_basic.node_id, 'author') AS authoraccess, nodepermissions( node_basic.node_id, 'group') AS groupaccess, nodepermissions( node_basic.node_id, 'other') AS otheraccess, nodepermissions( node_basic.node_id, 'guest') AS guestaccess, dynamicpermission( node_basic.node_id, 'author' ) as dynamicauthor_permission, dynamicpermission( node_basic.node_id, 'group' ) as dynamicgroup_permission, dynamicpermission( node_basic.node_id, 'other' ) as dynamicother_permission, dynamicpermission( node_basic.node_id, 'guest' ) as dynamicguest_permission, related_node_id( node_basic.node_id, 'group_usergroup') AS group_usergroup FROM node_basic LEFT JOIN node_modified ON node_modified.node_id = node_basic.node_id LEFT JOIN node_title ON node_basic.node_id = node_title.node_id LEFT JOIN node_statistics_hits ON node_basic.node_id = node_statistics_hits.node_id LEFT JOIN node_statistics_reputation ON node_basic.node_id = node_statistics_reputation.node_id LEFT JOIN node_lock ON node_basic.node_id = node_lock.node_id ; ; CREATE FUNCTION select_sqltables_nodetype( bigint, text ) RETURNS varchar AS $$ DECLARE node_id ALIAS FOR $1; tabletype ALIAS FOR $2; tablename varchar; tablelist varchar := ''; BEGIN FOR tablename IN SELECT sqltable.sqltable_name FROM sqltable, sqltable_type, node_sqltable WHERE node_sqltable.nodetype_id = node_id AND node_sqltable.sqltable = sqltable.sqltable_pk AND sqltable.type = sqltable_type_pk AND sqltable_type.sqltable_type = tabletype LOOP IF tablelist <> '' THEN tablelist := tablelist || ',' || tablename; ELSE tablelist := tablename; END IF; END LOOP; RETURN tablelist; END; $$ LANGUAGE plpgsql ; CREATE VIEW "nodetype" AS SELECT node_basic.node_id AS nodetype_id, related_node_id( node_basic.node_id, 'restrict_nodetype' ) AS restrict_nodetype, related_node_id( node_basic.node_id, 'extends_nodetype' ) AS extends_nodetype, ( SELECT (CASE ( SELECT b.behaviour FROM node_authorisation a, permission_type t, permission_behaviour b WHERE a.node_id = node_basic.node_id AND a.permission_type = t.permission_type_pk AND t.permission = 'restrictdupes' AND a.permission_behaviour = b.permission_behaviour_pk ) WHEN 'enable' THEN 1 WHEN 'disable' THEN 0 WHEN 'inherit' THEN -1 END ) ) AS restrictdupes, ( SELECT select_sqltables_nodetype( node_basic.node_id, 'attributetable' ) ) AS sqltable, ( SELECT select_sqltables_nodetype( node_basic.node_id, 'grouptable' ) ) AS grouptable, nodepermissions( node_basic.node_id, 'defaultauthor' ) AS defaultauthoraccess, nodepermissions( node_basic.node_id, 'defaultgroup' ) AS defaultgroupaccess, nodepermissions( node_basic.node_id, 'defaultother' ) AS defaultotheraccess, nodepermissions( node_basic.node_id, 'defaultguest' ) AS defaultguestaccess, related_node_id( node_basic.node_id, 'defaultgroup_usergroup') AS defaultgroup_usergroup, dynamicpermission ( node_basic.node_id, 'defaultauthor') AS defaultauthor_permission, dynamicpermission ( node_basic.node_id, 'defaultgroup') AS defaultgroup_permission, dynamicpermission ( node_basic.node_id, 'defaultother') AS defaultother_permission, dynamicpermission ( node_basic.node_id, 'defaultguest') AS defaultguest_permission, ( SELECT maxrevisions FROM nodebase_node_revisions r WHERE r.node_id = node_basic.node_id ) AS maxrevisions, ( SELECT (CASE ( SELECT b.behaviour FROM node_authorisation a, permission_type t, permission_behaviour b WHERE a.node_id = node_basic.node_id AND a.permission_type = t.permission_type_pk AND t.permission = 'canworkspace' AND a.permission_behaviour = b.permission_behaviour_pk ) WHEN 'enable' THEN 1 WHEN 'disable' THEN 0 WHEN 'inherit' THEN -1 END ) ) AS canworkspace FROM node_basic LEFT JOIN nodegroup_restrict_type ON nodegroup_restrict_type.group_nodetype_id = node_basic.node_id LEFT JOIN nodebase_restrictdupes ON nodebase_restrictdupes.nodetype_id = node_basic.node_id WHERE type_nodetype = 1; ; CREATE OR REPLACE FUNCTION insert_permissions (bigint, text, text) RETURNS VOID AS $$ INSERT INTO node_access ( node_id, user_type, permission_type, permission_behaviour ) SELECT $1, user_type.user_type_pk, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM user_type, permission_type, permission_behaviour WHERE permission_type.permission = 'read' AND user_type.usertype = $2 AND permission_behaviour.behaviour = CASE substring( $3 from 1 for 1 ) WHEN 'r' THEN 'enable' WHEN '-' THEN 'disable' WHEN 'i' THEN 'inherit' ELSE NULL END; INSERT INTO node_access ( node_id, user_type, permission_type, permission_behaviour ) SELECT $1, user_type.user_type_pk, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM user_type, permission_type, permission_behaviour WHERE permission_type.permission = 'write' AND user_type.usertype = $2 AND permission_behaviour.behaviour = CASE substring( $3 from 2 for 1 ) WHEN 'w' THEN 'enable' WHEN '-' THEN 'disable' WHEN 'i' THEN 'inherit' ELSE NULL END; INSERT INTO node_access ( node_id, user_type, permission_type, permission_behaviour ) SELECT $1, user_type.user_type_pk, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM user_type, permission_type, permission_behaviour WHERE permission_type.permission = 'execute' AND user_type.usertype = $2 AND permission_behaviour.behaviour = CASE substring( $3 from 3 for 1 ) WHEN 'x' THEN 'enable' WHEN '-' THEN 'disable' WHEN 'i' THEN 'inherit' ELSE NULL END; INSERT INTO node_access ( node_id, user_type, permission_type, permission_behaviour ) SELECT $1, user_type.user_type_pk, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM user_type, permission_type, permission_behaviour WHERE permission_type.permission = 'delete' AND user_type.usertype = $2 AND permission_behaviour.behaviour = CASE substring( $3 from 4 for 1 ) WHEN 'd' THEN 'enable' WHEN '-' THEN 'disable' WHEN 'i' THEN 'inherit' ELSE NULL END; INSERT INTO node_access ( node_id, user_type, permission_type, permission_behaviour ) SELECT $1, user_type.user_type_pk, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM user_type, permission_type, permission_behaviour WHERE permission_type.permission = 'create' AND user_type.usertype = $2 AND substring( $3 from 5 for 1 ) <> '' AND permission_behaviour.behaviour = CASE substring( $3 from 5 for 1 ) WHEN 'c' THEN 'enable' WHEN '-' THEN 'disable' WHEN 'i' THEN 'inherit' ELSE NULL END; $$ LANGUAGE SQL; ; CREATE OR REPLACE FUNCTION update_permissions (bigint, text, text) RETURNS VOID AS $$ DELETE FROM node_access WHERE node_access.node_id = $1 AND user_type = ( SELECT user_type.user_type_pk FROM user_type where user_type.usertype = $2 ); SELECT insert_permissions( $1, $2, $3 ); $$ LANGUAGE SQL; ; CREATE FUNCTION insert_node_relation (bigint, bigint, varchar) RETURNS VOID AS $$ INSERT INTO node_relationship (hasa_node, node, relation_type ) SELECT $2, $1, node_relation_type.node_relation_type_pk FROM node_relation_type WHERE node_relation_type.name = $3 AND $2 IS NOT NULL; $$ LANGUAGE SQL; ; CREATE FUNCTION insert_dynamic_permission ( bigint, bigint, varchar ) RETURNS VOID AS $$ --node_id, permission_id, user_type INSERT INTO node_relationship_usertype (node, with_node, relation_type, user_type ) SELECT $1, $2, ( SELECT node_relation_type_pk FROM node_relation_type WHERE name = 'dynamic permission' ), ( SELECT user_type_pk FROM user_type WHERE user_type.usertype = $3) WHERE $2 IS NOT NULL; $$ LANGUAGE SQL; ; CREATE RULE _insert_node AS ON INSERT TO node DO INSTEAD ( INSERT INTO node_basic ( type_nodetype, createtime ) VALUES ( NEW.type_nodetype, now() ); SELECT insert_node_relation( currval('node_basic_node_id_seq'), NEW.author_user, 'author_user' ); INSERT INTO node_title (title, node_id ) SELECT NEW.title, currval('node_basic_node_id_seq') WHERE NEW.title IS NOT NULL; INSERT INTO node_statistics_hits (hits, node_id ) SELECT NEW.hits, currval('node_basic_node_id_seq') WHERE NEW.hits IS NOT NULL; SELECT insert_node_relation ( currval('node_basic_node_id_seq'), NEW.loc_location, 'loc_location' ); INSERT INTO node_statistics_reputation (reputation, node_id ) SELECT NEW.reputation, currval('node_basic_node_id_seq') WHERE NEW.reputation IS NOT NULL; INSERT INTO node_lock (locktime, lockby_user, node_id ) SELECT NEW.locktime, NEW.lockby_user, currval('node_basic_node_id_seq') WHERE NEW.locktime IS NOT NULL; SELECT insert_node_relation( currval('node_basic_node_id_seq'), NEW.group_usergroup, 'group_usergroup' ); SELECT insert_permissions( currval('node_basic_node_id_seq'), 'author', NEW.authoraccess ); SELECT insert_permissions( currval('node_basic_node_id_seq'), 'group', NEW.groupaccess ); SELECT insert_permissions( currval('node_basic_node_id_seq'), 'other', NEW.otheraccess ); SELECT insert_permissions( currval('node_basic_node_id_seq'), 'guest', NEW.guestaccess ); SELECT insert_dynamic_permission( NEW.node_id, NEW.dynamicauthor_permission, 'author' ); SELECT insert_dynamic_permission( NEW.node_id, NEW.dynamicauthor_permission, 'group' ); SELECT insert_dynamic_permission( NEW.node_id, NEW.dynamicauthor_permission, 'other' ); SELECT insert_dynamic_permission( NEW.node_id, NEW.dynamicauthor_permission, 'guest' ); ) ; CREATE FUNCTION update_dynamicpermission (bigint, text, bigint ) RETURNS VOID AS $$ -- node_id, author type, permission_id DELETE FROM node_relationship_usertype WHERE node = $1 AND relation_type = (SELECT node_relation_type_pk FROM node_relation_type WHERE node_relation_type.name = 'dynamic permission' ) AND user_type = ( SELECT user_type_pk FROM user_type WHERE usertype = $2 ) AND $3 IS NULL; UPDATE node_relationship_usertype SET with_node = $3 WHERE node = $1 AND user_type = ( SELECT user_type_pk FROM user_type WHERE user_type.usertype = $2 ) AND relation_type = ( SELECT node_relation_type_pk FROM node_relation_type WHERE node_relation_type.name = 'dynamic permission' ) AND $3 IS NOT NULL AND $3 <> 0; INSERT INTO node_relationship_usertype (with_node, user_type, node, relation_type) SELECT $3, ( SELECT user_type_pk FROM user_type WHERE usertype = $2 ), $1, ( SELECT node_relation_type_pk FROM node_relation_type where name = 'dynamic permission') WHERE $3 IS NOT NULL AND $3 <> 0 AND NOT EXISTS ( SELECT * FROM node_relationship_usertype, user_type, node_relation_type WHERE node_relationship_usertype.node = $1 AND node_relationship_usertype.user_type = ( SELECT user_type.user_type_pk FROM user_type WHERE usertype = $2 ) AND node_relationship_usertype.relation_type = ( SELECT node_relation_type_pk from node_relation_type where name = 'dynamic permission')); $$ LANGUAGE SQL; ; -- First arg is the node_id from. The second is the 'has-a' node. The third is the relationship type. CREATE FUNCTION update_node_relation (bigint, bigint, varchar ) RETURNS VOID AS $$ DELETE FROM node_relationship WHERE $1 = node_relationship.node AND node_relationship.relation_type = ( SELECT node_relation_type.node_relation_type_pk FROM node_relation_type WHERE node_relation_type.name = $3 ) AND $2 IS NULL; UPDATE node_relationship SET hasa_node = $2 WHERE node_relationship.node = $1 AND $2 IS NOT NULL AND node_relationship.relation_type = ( SELECT node_relation_type_pk FROM node_relation_type WHERE node_relation_type.name = $3); INSERT INTO node_relationship (hasa_node, node, relation_type ) SELECT $2, $1, node_relation_type.node_relation_type_pk FROM node_relation_type WHERE node_relation_type.name = $3 AND $2 IS NOT NULL AND NOT EXISTS ( SELECT * FROM node_relationship, node_relation_type WHERE node_relationship.node = $1 AND node_relationship.relation_type = node_relation_type.node_relation_type_pk AND node_relation_type.name = $3 ); $$ LANGUAGE SQL; ; CREATE RULE _update_node AS ON UPDATE TO node DO INSTEAD ( UPDATE node_basic SET type_nodetype = NEW.type_nodetype WHERE NEW.type_nodetype <> OLD.type_nodetype AND NEW.node_id = node_basic.node_id; SELECT update_node_relation( NEW.node_id, NEW.author_user, 'author_user' ); DELETE FROM node_title WHERE NEW.node_id = node_title.node_id AND NEW.title IS NULL; UPDATE node_title SET title = NEW.title WHERE NEW.node_id = node_title.node_id AND NEW.title IS NOT NULL; INSERT INTO node_title (title, node_id) SELECT NEW.title, NEW.node_id WHERE NEW.title IS NOT NULL AND NOT EXISTS ( SELECT * FROM node_title WHERE node_title.node_id = NEW.node_id ); DELETE FROM node_statistics_hits WHERE NEW.node_id = node_statistics_hits.node_id AND NEW.hits IS NULL; UPDATE node_statistics_hits SET hits = NEW.hits WHERE NEW.node_id = node_statistics_hits.node_id; INSERT INTO node_statistics_hits (hits, node_id) SELECT NEW.hits, NEW.node_id WHERE NEW.hits IS NOT NULL AND NOT EXISTS ( SELECT * FROM node_statistics_hits WHERE node_statistics_hits.node_id = NEW.node_id ); SELECT update_node_relation( NEW.node_id, NEW.loc_location, 'loc_location' ); DELETE FROM node_statistics_reputation WHERE NEW.node_id = node_statistics_reputation.node_id AND NEW.reputation IS NULL; UPDATE node_statistics_reputation SET reputation = NEW.reputation WHERE NEW.node_id = node_statistics_reputation.node_id AND NEW.reputation IS NOT NULL; INSERT INTO node_statistics_reputation (reputation, node_id) SELECT NEW.reputation, NEW.node_id WHERE NEW.reputation IS NOT NULL AND NOT EXISTS ( SELECT * FROM node_statistics_reputation WHERE node_statistics_reputation.node_id = NEW.node_id ); DELETE FROM node_lock WHERE NEW.node_id = node_lock.node_id AND ( NEW.locktime IS NULL OR NEW.lockby_user IS NULL ); UPDATE node_lock SET locktime = NEW.locktime, lockby_user = NEW.lockby_user WHERE NEW.node_id = node_lock.node_id AND NEW.locktime IS NOT NULL AND NEW.lockby_user IS NOT NULL; INSERT INTO node_lock (locktime, lockby_user, node_id) SELECT NEW.locktime, NEW.lockby_user, NEW.node_id WHERE NEW.locktime IS NOT NULL AND NEW.lockby_user IS NOT NULL AND NOT EXISTS ( SELECT * FROM node_lock WHERE node_lock.node_id = NEW.node_id ); SELECT update_node_relation( NEW.node_id, NEW.group_usergroup, 'group_usergroup'); SELECT update_dynamicpermission( NEW.node_id, 'author', NEW.dynamicauthor_permission ); SELECT update_dynamicpermission( NEW.node_id, 'group', NEW.dynamicgroup_permission ); SELECT update_dynamicpermission( NEW.node_id, 'other', NEW.dynamicother_permission ); SELECT update_dynamicpermission( NEW.node_id, 'author', NEW.dynamicguest_permission ); SELECT update_permissions( NEW.node_id, 'author', NEW.authoraccess ); SELECT update_permissions( NEW.node_id, 'group', NEW.groupaccess ); SELECT update_permissions( NEW.node_id, 'other', NEW.otheraccess ); SELECT update_permissions( NEW.node_id, 'guest', NEW.guestaccess ); ) ; CREATE RULE _delete_node AS ON DELETE TO node DO INSTEAD ( DELETE FROM node_relationship WHERE node_relationship.node = OLD.node_id; DELETE FROM node_title WHERE node_id = OLD.node_id; DELETE FROM node_statistics_hits WHERE node_id = OLD.node_id; DELETE FROM node_location WHERE node_id = OLD.node_id; DELETE FROM node_statistics_reputation WHERE node_id = OLD.node_id; DELETE FROM node_lock WHERE node_id = OLD.node_id; DELETE FROM node_access WHERE node_id = OLD.node_id; DELETE FROM node_dynamicpermission WHERE node_id = OLD.node_id; DELETE FROM node_basic WHERE node_id = OLD.node_id; ) ; CREATE OR REPLACE FUNCTION split_on_comma(text) RETURNS SETOF varchar AS $$ DECLARE index INTEGER := 1; tablename varchar; BEGIN IF $1 IS NULL THEN RETURN; END IF; LOOP tablename := split_part( $1, ',',index ); IF tablename = '' THEN EXIT; END IF; index := index + 1; RETURN NEXT tablename; END LOOP; RETURN; END; $$ LANGUAGE plpgsql ; CREATE FUNCTION insert_sqltable_data( text, text, bigint ) RETURNS VOID AS $$ DECLARE tablelist ALIAS FOR $1; tabletype ALIAS FOR $2; node_id ALIAS FOR $3; tablename varchar; BEGIN FOR tablename IN SELECT * FROM split_on_comma( tablelist ) LOOP INSERT INTO sqltable (sqltable_name, type ) SELECT tablename, sqltable_type_pk FROM sqltable_type WHERE sqltable_type.sqltable_type = tabletype AND NOT EXISTS ( SELECT * FROM sqltable WHERE sqltable.sqltable_name = tablename ); INSERT INTO node_sqltable (nodetype_id, sqltable) SELECT node_id, sqltable_pk FROM sqltable WHERE sqltable_name = tablename AND NOT EXISTS ( SELECT * FROM node_sqltable, sqltable_type, sqltable WHERE node_sqltable.nodetype_id = node_id AND node_sqltable.sqltable = sqltable.sqltable_pk and sqltable.type = sqltable_type.sqltable_type_pk and sqltable_type.sqltable_type = tabletype AND sqltable.sqltable_name = tablename); END LOOP; RETURN; END; $$ LANGUAGE plpgsql ; CREATE RULE _insert_nodetype AS ON INSERT TO nodetype DO INSTEAD ( SELECT insert_node_relation( NEW.nodetype_id, NEW.restrict_nodetype, 'restrict_nodetype'); SELECT insert_node_relation( NEW.nodetype_id, NEW.extends_nodetype, 'extends_nodetype') WHERE NEW.extends_nodetype <> 0; INSERT INTO node_authorisation ( node_id, permission_type, permission_behaviour ) SELECT NEW.nodetype_id, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM permission_type, permission_behaviour WHERE permission_type.permission = 'restrictdupes' AND permission_behaviour.behaviour = CASE NEW.restrictdupes WHEN '1' THEN 'enable' WHEN '0' THEN 'disable' WHEN '-1' THEN 'inherit' ELSE NULL END; SELECT insert_sqltable_data( NEW.sqltable, 'attributetable', NEW.nodetype_id ); SELECT insert_sqltable_data( NEW.grouptable, 'grouptable', NEW.nodetype_id ); SELECT insert_permissions( NEW.nodetype_id, 'defaultauthor', NEW.defaultauthoraccess ); SELECT insert_permissions( NEW.nodetype_id, 'defaultgroup', NEW.defaultgroupaccess ); SELECT insert_permissions( NEW.nodetype_id, 'defaultother', NEW.defaultotheraccess ); SELECT insert_permissions( NEW.nodetype_id, 'defaultguest', NEW.defaultguestaccess ); SELECT insert_node_relation( NEW.nodetype_id, NEW.defaultgroup_usergroup, 'defaultgroup_usergroup' ); SELECT insert_dynamic_permission ( NEW.nodetype_id, NEW.defaultauthor_permission, 'defaultauthor' ); SELECT insert_dynamic_permission ( NEW.nodetype_id, NEW.defaultgroup_permission, 'defaultgroup' ); SELECT insert_dynamic_permission ( NEW.nodetype_id, NEW.defaultother_permission, 'defaultother' ); SELECT insert_dynamic_permission ( NEW.nodetype_id, NEW.defaultguest_permission, 'defaultguest' ); INSERT INTO nodebase_node_revisions (node_id, maxrevisions) SELECT NEW.nodetype_id, NEW.maxrevisions WHERE NEW.maxrevisions IS NOT NULL; INSERT INTO node_authorisation ( node_id, permission_type, permission_behaviour ) SELECT NEW.nodetype_id, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM permission_type, permission_behaviour WHERE permission_type.permission = 'canworkspace' AND permission_behaviour.behaviour = CASE NEW.canworkspace WHEN '1' THEN 'enable' WHEN '0' THEN 'disable' WHEN '-1' THEN 'inherit' ELSE NULL END; ) ; CREATE FUNCTION update_sqltable_data( text, text, bigint ) RETURNS VOID AS $$ DECLARE tablelist ALIAS FOR $1; tabletype ALIAS FOR $2; node_id ALIAS FOR $3; tablename varchar; BEGIN DELETE FROM node_sqltable WHERE nodetype_id = node_id AND sqltable in ( SELECT sqltable_pk FROM sqltable, sqltable_type WHERE sqltable.type = sqltable_type_pk AND sqltable_type.sqltable_type = tabletype); PERFORM insert_sqltable_data( tablelist, tabletype, node_id ); RETURN; END; $$ LANGUAGE plpgsql ; CREATE FUNCTION update_node_authorisation (bigint, integer, varchar ) RETURNS VOID AS $$ -- nodetype_id, authorisation, authorisation_type DELETE FROM node_authorisation WHERE node_authorisation.node_id = $1 AND node_authorisation.permission_type = ( SELECT permission_type.permission_type_pk FROM permission_type WHERE permission_type.permission = $3) AND $2 IS NULL; UPDATE node_authorisation SET permission_behaviour = ( SELECT permission_behaviour_pk FROM permission_behaviour WHERE permission_behaviour.behaviour = CASE $2 WHEN '1' THEN 'enable' WHEN '0' THEN 'disable' WHEN '-1' THEN 'inherit' ELSE NULL END ) WHERE node_authorisation.node_id = $1 AND node_authorisation.permission_type = ( SELECT permission_type_pk FROM permission_type where permission_type.permission = $3 ); INSERT INTO node_authorisation ( node_id, permission_type, permission_behaviour ) SELECT $1, permission_type.permission_type_pk, permission_behaviour.permission_behaviour_pk FROM permission_type, permission_behaviour WHERE permission_type.permission = $3 AND NOT EXISTS ( SELECT * FROM node_authorisation, permission_type WHERE node_authorisation.node_id = $1 AND node_authorisation.permission_type = permission_type.permission_type_pk AND permission_type.permission = $3) AND permission_behaviour.behaviour = ( SELECT CASE $2 WHEN '1' THEN 'enable' WHEN '0' THEN 'disable' WHEN '-1' THEN 'inherit' ELSE NULL END ); $$ LANGUAGE SQL; ; CREATE RULE _update_nodetype AS ON UPDATE to nodetype DO INSTEAD ( SELECT update_node_relation( NEW.nodetype_id, NEW.restrict_nodetype, 'restrict_nodetype') WHERE NEW.restrict_nodetype <> 0; SELECT update_node_relation( NEW.nodetype_id, NEW.extends_nodetype, 'extends_nodetype') WHERE NEW.extends_nodetype <> 0; SELECT update_node_authorisation( NEW.nodetype_id, NEW.restrictdupes, 'restrictdupes'); SELECT update_sqltable_data( NEW.sqltable, 'attributetable', NEW.nodetype_id ); SELECT update_sqltable_data( NEW.grouptable, 'grouptable', NEW.nodetype_id ); SELECT update_permissions( NEW.nodetype_id, 'defaultauthor', NEW.defaultauthoraccess ); SELECT update_permissions( NEW.nodetype_id, 'defaultgroup', NEW.defaultgroupaccess ); SELECT update_permissions( NEW.nodetype_id, 'defaultother', NEW.defaultotheraccess ); SELECT update_permissions( NEW.nodetype_id, 'defaultguest', NEW.defaultguestaccess ); SELECT update_node_relation( NEW.nodetype_id, NEW.defaultgroup_usergroup, 'defaultgroup_usergroup' ) WHERE NEW.defaultgroup_usergroup <> 0; SELECT update_dynamicpermission ( NEW.nodetype_id, 'defaultauthor', NEW.defaultauthor_permission ); SELECT update_dynamicpermission ( NEW.nodetype_id, 'defaultgroup', NEW.defaultgroup_permission ); SELECT update_dynamicpermission ( NEW.nodetype_id, 'defaultother', NEW.defaultother_permission ); SELECT update_dynamicpermission ( NEW.nodetype_id, 'defaultguest', NEW.defaultguest_permission ); DELETE FROM nodebase_node_revisions WHERE nodebase_node_revisions.node_id = NEW.nodetype_id AND NEW.maxrevisions IS NULL; UPDATE nodebase_node_revisions SET maxrevisions=NEW.maxrevisions WHERE NEW.maxrevisions IS NOT NULL AND nodebase_node_revisions.node_id = NEW.nodetype_id AND EXISTS (SELECT * FROM nodebase_node_revisions where nodebase_node_revisions.node_id = NEW.nodetype_id ); INSERT INTO nodebase_node_revisions (node_id, maxrevisions ) SELECT NEW.nodetype_id, NEW.maxrevisions WHERE NEW.maxrevisions IS NOT NULL AND NOT EXISTS (SELECT * FROM nodebase_node_revisions WHERE nodebase_node_revisions.node_id = NEW.nodetype_id); SELECT update_node_authorisation ( NEW.nodetype_id, NEW.canworkspace, 'canworkspace' ); ) ; CREATE TABLE version ( version_id INTEGER PRIMARY KEY DEFAULT '0' NOT NULL, version INTEGER DEFAULT '1' NOT NULL ); INSERT INTO sqltable_type ( sqltable_type, description) VALUES ('attributetable', 'A table of this type contains node attribute data.') ; INSERT INTO sqltable_type ( sqltable_type, description) VALUES ('grouptable', 'A table of this type contains a list of nodes contained in a type.') ; INSERT INTO node_relation_type ( name, description ) VALUES ('author_user', 'the user node identified as author of a node') ; INSERT INTO node_relation_type ( name, description ) VALUES ('group_usergroup', 'the usergroup node associated with a node') ; INSERT INTO node_relation_type ( name, description ) VALUES ('defaultgroup_usergroup', 'the default usergroup node associated with a node') ; INSERT INTO node_relation_type ( name, description ) VALUES ('extends_nodetype', 'the nodetype that this node extends') ; INSERT INTO node_relation_type ( name, description ) VALUES ('type_nodetype', 'the nodetype node of a node') ; INSERT INTO node_relation_type ( name, description ) VALUES ('loc_location', 'the location node of a node') ; INSERT INTO node_relation_type ( name, description ) VALUES ('restrict_nodetype', 'for group nodes: restrict the nodes contained in this group to this type.') ; INSERT INTO node_relation_type ( name, description ) VALUES ('dynamic permission', 'where access to a node is determined by a perimssion node.') ; INSERT INTO node_relation_type ( name, description ) VALUES ('permission', 'a dynamic permission node for the node') ; INSERT INTO user_type (usertype, description) VALUES ('author', 'an author of a node'); INSERT INTO user_type (usertype, description) VALUES ('group', 'whether an author is a member of a group'); INSERT INTO user_type (usertype, description) VALUES ('other', 'a user is logged in but is neither in the relevant group not an author'); INSERT INTO user_type (usertype, description) VALUES ('guest', 'usually used to refer to an anonymous user or one that is not in any other category'); INSERT INTO user_type (usertype, description) VALUES ('defaultauthor', 'what an author type defaults to.'); INSERT INTO user_type (usertype, description) VALUES ('defaultgroup', 'what members of a group default to.'); INSERT INTO user_type (usertype, description) VALUES ('defaultother', 'what other users default to.'); INSERT INTO user_type (usertype, description) VALUES ('defaultguest', 'what guests default to.'); INSERT INTO permission_type (permission, description) VALUES ('read', 'the permission to read an object'); INSERT INTO permission_type (permission, description) VALUES ('write', 'the permission to write to an object'); INSERT INTO permission_type (permission, description) VALUES ('execute', 'the permission to "execute" an object, that is, run any code in it'); INSERT INTO permission_type (permission, description) VALUES ('delete', 'the permission to delete an object'); INSERT INTO permission_type (permission, description) VALUES ('create', 'the permission to create an object'); INSERT INTO permission_type (permission, description) VALUES ('canworkspace', 'whether the node can be workspaced'); INSERT INTO permission_type (permission, description) VALUES ('restrictdupes', 'whether the nodebase allows creation of nodes with a similar name'); INSERT INTO permission_behaviour (behaviour, description) VALUES ('enable', 'the permission for this object is enabled'); INSERT INTO permission_behaviour (behaviour, description) VALUES ('disable', 'the permission for this object is disabled'); INSERT INTO permission_behaviour (behaviour, description) VALUES ('inherit', 'the permission for this object is inherited according to some algorithm'); INSERT INTO node (node_id, type_nodetype, title, createtime, authoraccess, groupaccess, otheraccess, guestaccess ) VALUES (1,1,'nodetype',now(), 'iiii','rwxdc','-----','-----' ); INSERT INTO node (node_id, type_nodetype, title, createtime, authoraccess, groupaccess, otheraccess, guestaccess ) VALUES (2,1,'node',now(),'rwxd','-----','-----','-----'); INSERT INTO node (node_id, type_nodetype, title, createtime, authoraccess, groupaccess, otheraccess, guestaccess ) VALUES (3,1,'setting', now(),'rwxd','-----','-----','-----'); INSERT INTO nodetype (nodetype_id, restrict_nodetype, extends_nodetype, restrictdupes, sqltable, grouptable, defaultauthoraccess, defaultgroupaccess, defaultotheraccess, defaultguestaccess, defaultgroup_usergroup, defaultauthor_permission, defaultgroup_permission, defaultother_permission, defaultguest_permission, maxrevisions, canworkspace ) VALUES (1,NULL,2,1,'nodetype','','rwxd','rwxdc','-----','-----',NULL,NULL,NULL,NULL,NULL,-1,0); INSERT INTO nodetype (nodetype_id, restrict_nodetype, extends_nodetype, restrictdupes, sqltable, grouptable, defaultauthoraccess, defaultgroupaccess, defaultotheraccess, defaultguestaccess, defaultgroup_usergroup, defaultauthor_permission, defaultgroup_permission, defaultother_permission, defaultguest_permission, maxrevisions, canworkspace ) VALUES (2,NULL,NULL,1,'','','rwxd','r----','-----','-----',NULL,NULL,NULL,NULL,NULL,1000,1); INSERT INTO nodetype (nodetype_id, restrict_nodetype, extends_nodetype, restrictdupes, sqltable, grouptable, defaultauthoraccess, defaultgroupaccess, defaultotheraccess, defaultguestaccess, defaultgroup_usergroup, defaultauthor_permission, defaultgroup_permission, defaultother_permission, defaultguest_permission, maxrevisions, canworkspace ) VALUES (3,NULL,2,1,'setting','','rwxd','-----','-----','-----',NULL,NULL,NULL,NULL,NULL,-1,-1) |