-- Callbacks create table apm_package_callbacks ( version_id integer constraint apm_package_callbacks_vid_fk references apm_package_versions(version_id) on delete cascade, type varchar(40), proc varchar(300), constraint apm_package_callbacks_vt_un unique (version_id, type) ); comment on table apm_package_callbacks is ' This table holds names of Tcl procedures to invoke at the time (before or after) the package is installed, instantiated, or mounted. '; comment on column apm_package_callbacks.proc is ' Name of the Tcl proc. '; comment on column apm_package_callbacks.type is ' Indicates when the callback proc should be invoked, for example after-install. Valid values are given by the Tcl proc apm_supported_callback_types. '; -- Add column for auto-mount alter table apm_package_versions add auto_mount varchar(50); -- DRB: Set it null for all existing versions (probably not necessary but doesn't hurt) update apm_package_versions set auto_mount = NULL; comment on column apm_package_versions.auto_mount is ' A dir under the main site site node where an instance of the package will be mounted automatically upon installation. Useful for site-wide services that need mounting such as general-comments and notifications. '; -- DRB: Need to drop this view first in PG 7.3 since "cascade" isn't implemented in -- PG 7.2 and PG 7.3 doesn't let you drop a view if another depends on it. drop view apm_enabled_package_versions; -- Recreate views for auto-mount drop view apm_package_version_info; create view apm_package_version_info as select v.package_key, t.package_uri, t.pretty_name, t.singleton_p, t.initial_install_p, v.version_id, v.version_name, v.version_uri, v.summary, v.description_format, v.description, v.release_date, v.vendor, v.vendor_uri, v.auto_mount, v.enabled_p, v.installed_p, v.tagged_p, v.imported_p, v.data_model_loaded_p, v.activation_date, v.deactivation_date, coalesce(v.content_length,0) as tarball_length, distribution_uri, distribution_date from apm_package_types t, apm_package_versions v where v.package_key = t.package_key; create view apm_enabled_package_versions as select * from apm_package_version_info where enabled_p = 't'; create or replace function apm_package__highest_version (varchar) returns integer as ' declare highest_version__package_key alias for $1; v_version_id apm_package_versions.version_id%TYPE; begin select version_id into v_version_id from apm_package_version_info i where apm_package_version__sortable_version_name(version_name) = (select max(apm_package_version__sortable_version_name(v.version_name)) from apm_package_version_info v where v.package_key = highest_version__package_key) and package_key = highest_version__package_key; if NOT FOUND then return 0; else return v_version_id; end if; end;' language 'plpgsql'; -- Recreate functions for auto-mount create function apm_package_version__new (integer,varchar,varchar,varchar,varchar,varchar,varchar,timestamptz,varchar,varchar,varchar,boolean,boolean) returns integer as ' declare apm_pkg_ver__version_id alias for $1; -- default null apm_pkg_ver__package_key alias for $2; apm_pkg_ver__version_name alias for $3; -- default null apm_pkg_ver__version_uri alias for $4; apm_pkg_ver__summary alias for $5; apm_pkg_ver__description_format alias for $6; apm_pkg_ver__description alias for $7; apm_pkg_ver__release_date alias for $8; apm_pkg_ver__vendor alias for $9; apm_pkg_ver__vendor_uri alias for $10; apm_pkg_ver__auto_mount alias for $11; apm_pkg_ver__installed_p alias for $12; -- default ''f'' apm_pkg_ver__data_model_loaded_p alias for $13; -- default ''f'' v_version_id apm_package_versions.version_id%TYPE; begin if apm_pkg_ver__version_id is null then select nextval(''t_acs_object_id_seq'') into v_version_id from dual; else v_version_id := apm_pkg_ver__version_id; end if; v_version_id := acs_object__new( v_version_id, ''apm_package_version'', now(), null, null, null ); insert into apm_package_versions (version_id, package_key, version_name, version_uri, summary, description_format, description, release_date, vendor, vendor_uri, auto_mount, installed_p, data_model_loaded_p) values (v_version_id, apm_pkg_ver__package_key, apm_pkg_ver__version_name, apm_pkg_ver__version_uri, apm_pkg_ver__summary, apm_pkg_ver__description_format, apm_pkg_ver__description, apm_pkg_ver__release_date, apm_pkg_ver__vendor, apm_pkg_ver__vendor_uri, apm_pkg_ver__auto_mount, apm_pkg_ver__installed_p, apm_pkg_ver__data_model_loaded_p); return v_version_id; end;' language 'plpgsql'; create or replace function apm_package_version__edit (integer,integer,varchar,varchar,varchar,varchar,varchar,timestamptz,varchar,varchar,varchar,boolean,boolean) returns integer as ' declare edit__new_version_id alias for $1; -- default null edit__version_id alias for $2; edit__version_name alias for $3; -- default null edit__version_uri alias for $4; edit__summary alias for $5; edit__description_format alias for $6; edit__description alias for $7; edit__release_date alias for $8; edit__vendor alias for $9; edit__vendor_uri alias for $10; edit__auto_mount alias for $11; edit__installed_p alias for $12; -- default ''f'' edit__data_model_loaded_p alias for $13; -- default ''f'' v_version_id apm_package_versions.version_id%TYPE; version_unchanged_p integer; begin -- Determine if version has changed. select case when count(*) = 0 then 0 else 1 end into version_unchanged_p from apm_package_versions where version_id = edit__version_id and version_name = edit__version_name; if version_unchanged_p <> 1 then v_version_id := apm_package_version__copy( edit__version_id, edit__new_version_id, edit__version_name, edit__version_uri, ''f'' ); else v_version_id := edit__version_id; end if; update apm_package_versions set version_uri = edit__version_uri, summary = edit__summary, description_format = edit__description_format, description = edit__description, release_date = date_trunc(''days'',now()), vendor = edit__vendor, vendor_uri = edit__vendor_uri, auto_mount = edit__auto_mount, installed_p = edit__installed_p, data_model_loaded_p = edit__data_model_loaded_p where version_id = v_version_id; return v_version_id; end;' language 'plpgsql'; create or replace function apm_package_version__copy (integer,integer,varchar,varchar,boolean) returns integer as ' declare copy__version_id alias for $1; copy__new_version_id alias for $2; -- default null copy__new_version_name alias for $3; copy__new_version_uri alias for $4; copy__copy_owners_p alias for $5; v_version_id integer; begin v_version_id := acs_object__new( copy__new_version_id, ''apm_package_version'', now(), null, null, null ); insert into apm_package_versions(version_id, package_key, version_name, version_uri, summary, description_format, description, release_date, vendor, vendor_uri, auto_mount) select v_version_id, package_key, copy__new_version_name, copy__new_version_uri, summary, description_format, description, release_date, vendor, vendor_uri, auto_mount from apm_package_versions where version_id = copy__version_id; insert into apm_package_dependencies(dependency_id, version_id, dependency_type, service_uri, service_version) select nextval(''t_acs_object_id_seq''), v_version_id, dependency_type, service_uri, service_version from apm_package_dependencies where version_id = copy__version_id; insert into apm_package_files(file_id, version_id, path, file_type, db_type) select nextval(''t_acs_object_id_seq''), v_version_id, path, file_type, db_type from apm_package_files where version_id = copy__version_id; insert into apm_package_callbacks (version_id, type, proc) select v_version_id, type, proc from apm_package_callbacks where version_id = copy__version_id; if copy__copy_owners_p then insert into apm_package_owners(version_id, owner_uri, owner_name, sort_key) select v_version_id, owner_uri, owner_name, sort_key from apm_package_owners where version_id = copy__version_id; end if; return v_version_id; end;' language 'plpgsql'; -- DRB: Fix the incredibly slow execution of acs_privilege__add_child() drop view acs_privilege_descendant_map_view; create view acs_privilege_descendant_map_view as select distinct h1.privilege, h2.child_privilege as descendant from acs_privilege_hierarchy_index h1, acs_privilege_hierarchy_index h2 where h2.tree_sortkey between h1.tree_sortkey and tree_right(h1.tree_sortkey) union select privilege, privilege from acs_privileges; drop trigger acs_priv_hier_ins_del_tr on acs_privilege_hierarchy; drop function acs_priv_hier_ins_del_tr (); create or replace function acs_priv_hier_ins_del_tr () returns opaque as ' declare new_value integer; new_key varbit default null; v_rec record; deleted_p boolean; begin -- if more than one node was deleted the second trigger call -- will error out. This check avoids that problem. if TG_OP = ''DELETE'' then select count(*) = 0 into deleted_p from acs_privilege_hierarchy_index where old.privilege = privilege and old.child_privilege = child_privilege; if deleted_p then return new; end if; end if; -- recalculate the table from scratch. delete from acs_privilege_hierarchy_index; -- first find the top nodes of the tree for v_rec in select privilege, child_privilege from acs_privilege_hierarchy where privilege NOT in (select distinct child_privilege from acs_privilege_hierarchy) LOOP -- top level node, so find the next key at this level. select max(tree_leaf_key_to_int(tree_sortkey)) into new_value from acs_privilege_hierarchy_index where tree_level(tree_sortkey) = 1; -- insert the new node insert into acs_privilege_hierarchy_index (privilege, child_privilege, tree_sortkey) values (v_rec.privilege, v_rec.child_privilege, tree_next_key(null, new_value)); -- now recurse down from this node PERFORM priv_recurse_subtree(tree_next_key(null, new_value), v_rec.child_privilege); end LOOP; -- materialize the map view to speed up queries -- DanW (dcwickstrom@earthlink.net) 30 Jan, 2003 delete from acs_privilege_descendant_map; insert into acs_privilege_descendant_map (privilege, descendant) select privilege, descendant from acs_privilege_descendant_map_view; return new; end;' language 'plpgsql'; create trigger acs_priv_hier_ins_del_tr after insert or delete on acs_privilege_hierarchy for each row execute procedure acs_priv_hier_ins_del_tr (); ------------------------------------------------------------------------------------------------ -- DRB: composition_rel triggers for permission expansion failed to find its way into 4.6.1. -- I'm not providing code to correct party_approved_member_map because this trigger's only -- important when a composition_rel is added to groups which already have members, something -- existing code doesn't do. drop trigger composition_rels_in_tr on composition_rels; drop function composition_rels_in_tr (); create or replace function composition_rels_in_tr () returns opaque as ' declare v_object_id_one acs_rels.object_id_one%TYPE; v_object_id_two acs_rels.object_id_two%TYPE; v_rel_type acs_rels.rel_type%TYPE; v_error text; map record; begin -- First check if added this relation violated any relational constraints v_error := rel_constraint__violation(new.rel_id); if v_error is not null then raise EXCEPTION ''-20000: %'', v_error; end if; select object_id_one, object_id_two, rel_type into v_object_id_one, v_object_id_two, v_rel_type from acs_rels where rel_id = new.rel_id; -- Insert a row for me in group_element_index insert into group_element_index (group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type) values (v_object_id_one, v_object_id_two, new.rel_id, v_object_id_one, v_rel_type, ''composition_rel''); -- Add to the denormalized party_approved_member_map perform party_approved_member__add(v_object_id_one, member_id, rel_id, rel_type) from group_approved_member_map m where group_id = v_object_id_two and not exists (select 1 from group_element_map where group_id = v_object_id_one and element_id = m.member_id and rel_id = m.rel_id); -- Make my elements be elements of my new composite group insert into group_element_index (group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type) select distinct v_object_id_one, element_id, rel_id, container_id, rel_type, ancestor_rel_type from group_element_map m where group_id = v_object_id_two and not exists (select 1 from group_element_map where group_id = v_object_id_one and element_id = m.element_id and rel_id = m.rel_id); -- For all direct or indirect containers of my new composite group, -- add me and add my elements for map in select distinct group_id from group_component_map where component_id = v_object_id_one LOOP -- Add a row for me insert into group_element_index (group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type) values (map.group_id, v_object_id_two, new.rel_id, v_object_id_one, v_rel_type, ''composition_rel''); -- Add to party_approved_member_map perform party_approved_member__add(map.group_id, member_id, rel_id, rel_type) from group_approved_member_map m where group_id = v_object_id_two and not exists (select 1 from group_element_map where group_id = map.group_id and element_id = m.member_id and rel_id = m.rel_id); -- Add rows for my elements insert into group_element_index (group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type) select distinct map.group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type from group_element_map m where group_id = v_object_id_two and not exists (select 1 from group_element_map where group_id = map.group_id and element_id = m.element_id and rel_id = m.rel_id); end loop; return new; end;' language 'plpgsql'; create trigger composition_rels_in_tr after insert on composition_rels for each row execute procedure composition_rels_in_tr (); -- -- TO DO: See if this can be optimized now that the member and component -- mapping tables have been combined -- drop trigger composition_rels_del_tr on composition_rels; drop function composition_rels_del_tr(); create or replace function composition_rels_del_tr () returns opaque as ' declare v_object_id_one acs_rels.object_id_one%TYPE; v_object_id_two acs_rels.object_id_two%TYPE; n_rows integer; v_error text; map record; begin -- First check if removing this relation would violate any relational constraints v_error := rel_constraint__violation_if_removed(old.rel_id); if v_error is not null then raise EXCEPTION ''-20000: %'', v_error; end if; select object_id_one, object_id_two into v_object_id_one, v_object_id_two from acs_rels where rel_id = old.rel_id; for map in select * from group_component_map where rel_id = old.rel_id LOOP delete from group_element_index where rel_id = old.rel_id; select count(*) into n_rows from group_component_map where group_id = map.group_id and component_id = map.component_id; if n_rows = 0 then perform party_approved_member__remove(map.group_id, member_id, rel_id, rel_type) from group_approved_member_map where group_id = map.group_id and container_id = map.component_id; delete from group_element_index where group_id = map.group_id and container_id = map.component_id and ancestor_rel_type = ''membership_rel''; end if; end loop; for map in select * from group_component_map where group_id in (select group_id from group_component_map where component_id = v_object_id_one union select v_object_id_one from dual) and component_id in (select component_id from group_component_map where group_id = v_object_id_two union select v_object_id_two from dual) and group_contains_p(group_id, component_id, rel_id) = ''f'' LOOP delete from group_element_index where group_id = map.group_id and element_id = map.component_id and rel_id = map.rel_id; select count(*) into n_rows from group_component_map where group_id = map.group_id and component_id = map.component_id; if n_rows = 0 then end if; perform party_approved_member__remove(map.group_id, member_id, rel_id, rel_type) from group_approved_member_map where group_id = map.group_id and container_id = map.component_id; delete from group_element_index where group_id = map.group_id and container_id = map.component_id and ancestor_rel_type = ''membership_rel''; end loop; return old; end;' language 'plpgsql'; create trigger composition_rels_del_tr before delete on composition_rels for each row execute procedure composition_rels_del_tr ();