Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,310 @@
+--
+-- packages/acs-kernel/sql/acs-create.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-08-22
+-- @cvs-id acs-create.sql,v 1.1.2.9 2000/08/24 07:09:18 rhs Exp
+--
+
+create table acs_magic_objects (
+ name varchar(100)
+ constraint acs_magic_objects_pk primary key,
+ object_id integer not null constraint acs_magic_objects_object_id_fk
+ references acs_objects(object_id)
+);
+
+create index acs_mo_object_id_idx on acs_magic_objects (object_id);
+
+comment on table acs_magic_objects is '
+ This table allows us to provide semantic names for certain special
+ objects like the site-wide organization, and the all users party.
+';
+
+-- create or replace package acs
+-- as
+--
+-- function add_user (
+-- user_id in users.user_id%TYPE default null,
+-- object_type in acs_objects.object_type%TYPE
+-- default 'user',
+-- creation_date in acs_objects.creation_date%TYPE
+-- default sysdate,
+-- creation_user in acs_objects.creation_user%TYPE
+-- default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null,
+-- email in parties.email%TYPE,
+-- url in parties.url%TYPE default null,
+-- first_names in persons.first_names%TYPE,
+-- last_name in persons.last_name%TYPE,
+-- password in users.password%TYPE,
+-- salt in users.salt%TYPE,
+-- password_question in users.password_question%TYPE default null,
+-- password_answer in users.password_answer%TYPE default null,
+-- screen_name in users.screen_name%TYPE default null,
+-- email_verified_p in users.email_verified_p%TYPE default 't',
+-- member_state in membership_rels.member_state%TYPE default 'approved'
+-- )
+-- return users.user_id%TYPE;
+--
+-- procedure remove_user (
+-- user_id in users.user_id%TYPE
+-- );
+--
+-- function magic_object_id (
+-- name in acs_magic_objects.name%TYPE
+-- ) return acs_objects.object_id%TYPE;
+--
+-- end acs;
+
+-- show errors
+
+-- create or replace package body acs
+-- function add_user
+create function acs__add_user (integer,varchar,timestamp,integer,varchar,varchar,varchar,varchar,varchar,char,char,varchar,varchar,varchar,boolean,varchar)
+returns integer as '
+declare
+ user_id alias for $1;
+ object_type alias for $2;
+ creation_date alias for $3;
+ creation_user alias for $4;
+ creation_ip alias for $5;
+ email alias for $6;
+ url alias for $7;
+ first_names alias for $8;
+ last_name alias for $9;
+ password alias for $10;
+ salt alias for $11;
+ password_question alias for $12;
+ password_answer alias for $13;
+ screen_name alias for $14;
+ email_verified_p alias for $15;
+ member_state alias for $16;
+ v_user_id users.user_id%TYPE;
+ v_rel_id membership_rels.rel_id%TYPE;
+begin
+ v_user_id := acs_user__new (user_id, object_type, creation_date,
+ creation_user, creation_ip, email,
+ url, first_names, last_name, password,
+ salt, password_question, password_answer,
+ screen_name, email_verified_p,null);
+
+ v_rel_id := membership_rel__new (
+ null,
+ ''membership_rel'',
+ acs__magic_object_id(''registered_users''),
+ v_user_id,
+ member_state
+ null,
+ null);
+
+ PERFORM acs_permission__grant_permission (
+ v_user_id,
+ v_user_id,
+ ''read''
+ );
+
+ PERFORM acs_permission__grant_permission (
+ v_user_id,
+ v_user_id,
+ ''write''
+ );
+
+ return v_user_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure remove_user
+create function acs__remove_user (integer)
+returns integer as '
+declare
+ remove_user__user_id alias for $1;
+begin
+ delete from users
+ where user_id = remove_user__user_id;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function magic_object_id
+create function acs__magic_object_id (varchar)
+returns integer as '
+declare
+ magic_object_id__name alias for $1;
+ magic_object_id__object_id acs_objects.object_id%TYPE;
+begin
+ select object_id
+ into magic_object_id__object_id
+ from acs_magic_objects
+ where name = magic_object_id__name;
+
+ return magic_object_id__object_id;
+
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
+-- ******************************************************************
+-- * Community Core API
+-- ******************************************************************
+
+create view registered_users
+as
+ select p.email, p.url, pe.first_names, pe.last_name, u.*, mr.member_state
+ from parties p, persons pe, users u, group_member_map m, membership_rels mr
+ where party_id = person_id
+ and person_id = user_id
+ and u.user_id = m.member_id
+ and m.rel_id = mr.rel_id
+ and m.group_id = acs__magic_object_id('registered_users')
+ and mr.member_state = 'approved'
+ and u.email_verified_p = 't';
+
+create view cc_users
+as
+select o.*, pa.*, pe.*, u.*, mr.member_state, mr.rel_id
+from acs_objects o, parties pa, persons pe, users u, group_member_map m, membership_rels mr
+where o.object_id = pa.party_id
+and pa.party_id = pe.person_id
+and pe.person_id = u.user_id
+and u.user_id = m.member_id
+and m.group_id = acs__magic_object_id('registered_users')
+and m.rel_id = mr.rel_id
+and m.container_id = m.group_id;
+
+-----------------------------------
+-- Community Core Initialization --
+-----------------------------------
+
+-- The very first thing we must do is create the security_context_root
+-- object.
+
+create function inline_0 ()
+returns integer as '
+declare
+ root_id integer;
+begin
+
+ root_id := acs_object__new (
+ 0,
+ ''acs_object'',
+ now(),
+ null,
+ null,
+ null
+ );
+
+ insert into acs_magic_objects
+ (name, object_id)
+ values
+ (''security_context_root'', 0);
+
+
+ return root_id;
+
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
+
+create function inline_1 ()
+returns integer as '
+begin
+ --------------------------------------------------------------
+ -- Some privilege that will be fundamental to all objects. --
+ --------------------------------------------------------------
+
+ PERFORM acs_privilege__create_privilege(''read'', null, null);
+ PERFORM acs_privilege__create_privilege(''write'', null, null);
+ PERFORM acs_privilege__create_privilege(''create'', null, null);
+ PERFORM acs_privilege__create_privilege(''delete'', null, null);
+ PERFORM acs_privilege__create_privilege(''admin'', null, null);
+
+ ---------------------------------------------------------
+ -- Administrators can read, write, create, and delete. --
+ ---------------------------------------------------------
+
+ PERFORM acs_privilege__add_child(''admin'', ''read'');
+ PERFORM acs_privilege__add_child(''admin'', ''write'');
+ PERFORM acs_privilege__add_child(''admin'', ''create'');
+ PERFORM acs_privilege__add_child(''admin'', ''delete'');
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_1 ();
+
+drop function inline_1 ();
+
+
+-- show errors
+
+create function inline_2 ()
+returns integer as '
+declare
+ v_object_id integer;
+begin
+
+ insert into acs_objects
+ (object_id, object_type)
+ values
+ (-1, ''party'');
+
+ insert into parties
+ (party_id)
+ values
+ (-1);
+
+ insert into acs_magic_objects
+ (name, object_id)
+ values
+ (''the_public'', -1);
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_2 ();
+
+drop function inline_2 ();
+
+
+create function inline_3 ()
+returns integer as '
+declare
+ group_id integer;
+begin
+
+ group_id := acs_group__new (
+ -2,
+ ''group'',
+ now(),
+ null,
+ null,
+ null,
+ null,
+ ''Registered Users'',
+ null,
+ null
+ );
+
+ insert into acs_magic_objects
+ (name, object_id)
+ values
+ (''registered_users'', -2);
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_3 ();
+
+drop function inline_3 ();
+
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,14 @@
+--
+-- packages/acs-kernel/sql/acs-drop.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-08-22
+-- @cvs-id acs-drop.sql,v 1.5 2000/10/24 22:26:18 bquinn Exp
+--
+
+drop view cc_users;
+drop view registered_users;
+\t
+select drop_package('acs');
+\t
+drop table acs_magic_objects;
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,169 @@
+--
+-- /packages/acs-kernel/sql/acs-install.sql
+--
+-- Complete the install of the system by setting up some default URL mappings.
+--
+-- @author Bryan Quinn (bquinn@arsdigita.com
+-- @creation-date 2000/10/01
+-- @cvs-id acs-install.sql,v 1.9.2.1 2001/01/12 18:32:21 dennis Exp
+--
+
+create function inline_0 ()
+returns integer as '
+declare
+ kernel_id apm_packages.package_id%TYPE;
+ node_id site_nodes.node_id%TYPE;
+ main_site_id site_nodes.node_id%TYPE;
+ admin_id apm_packages.package_id%TYPE;
+ docs_id apm_packages.package_id%TYPE;
+ api_doc_id apm_packages.package_id%TYPE;
+ schema_user varchar(100);
+ jobnum integer;
+begin
+ kernel_id := apm_service__new (
+ null,
+ ''ACS Kernel'',
+ ''acs-kernel'',
+ ''apm_service'',
+ now(),
+ null,
+ null,
+ acs.magic_object_id(''default_context'')
+ );
+
+
+ PERFORM apm_package__enable (kernel_id);
+
+ main_site_id := apm_service__new(
+ null,
+ ''Main Site'',
+ ''acs-subsite'',
+ ''apm_service'',
+ now(),
+ null,
+ null,
+ acs__magic_object_id(''default_context'')
+ );
+
+
+ PERFORM apm_package__enable (main_site_id);
+
+ node_id := site_node__new (
+ null,
+ null,
+ '''',
+ main_site_id,
+ ''t'',
+ ''t'',
+ null,
+ null
+ );
+
+ PERFORM acs_permission__grant_permission (
+ main_site_id,
+ acs__magic_object_id(''the_public''),
+ ''read''
+ );
+
+ admin_id := apm_service__new (
+ null,
+ ''ACS Administration'',
+ ''acs-admin'',
+ ''apm_service'',
+ now(),
+ null,
+ null,
+ null
+ );
+
+ PERFORM apm_package__enable (admin_id);
+
+ node_id := site_node__new (
+ null,
+ site_node__node_id(''/'', null),
+ ''acs-admin'',
+ admin_id
+ ''t'',
+ ''t'',
+ null,
+ null
+ );
+
+ docs_id := apm_service__new (
+ null,
+ ''ACS Core Documents'',
+ ''acs-core-docs'',
+ ''apm_service'',
+ now(),
+ null,
+ null,
+ main_site_id
+ );
+
+ node_id := site_node__new (
+ null,
+ site_node.node_id(''/''),
+ ''doc'',
+ docs_id,
+ ''t'',
+ ''t'',
+ null,
+ null
+ );
+
+ api_doc_id := apm_service__new (
+ null,
+ ''ACS API Browser'',
+ ''acs-api-browser'',
+ ''apm_service'',
+ now(),
+ null,
+ null,
+ main_site_id
+ );
+
+ PERFORM apm_package__enable (api_doc_id);
+
+ -- Set default permissions for ACS API Browser so
+ -- that only users logged in can view it
+
+ update acs_objects
+ set security_inherit_p = 'f'
+ where object_id = api_doc_id;
+
+ PERFORM acs_permission__grant_permission (
+ api_doc_id,
+ acs__magic_object_id (''registered_users''),
+ ''read''
+ );
+
+ api_doc_id := site_node__new (
+ null,
+ site_node.node_id(''/''),
+ ''api-doc'',
+ api_doc_id,
+ ''t'',
+ ''t'',
+ null,
+ null
+ );
+
+ -- select user into schema_user from dual;
+
+ -- dbms_job.submit (
+ -- jobnum,
+ -- 'dbms_stats.gather_schema_stats (''' || schema_user || ''', 10, cascade => true);',
+ -- trunc(sysdate+1) + 4/24,
+ -- 'trunc(sysdate+1) + 4/24'
+ );
+
+
+ return null;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-kernel-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-kernel-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-kernel-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,34 @@
+--
+-- /packages/acs-kernel/sql/acs-kernel-create.sql
+--
+-- Load the entire ACS Core package's data model
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @creation-date 2000/07/29
+-- @cvs-id acs-kernel-create.sql,v 1.7.2.1 2001/01/12 22:47:21 oumi Exp
+--
+
+-- set feedback off
+
+\i postgresql.sql
+\i acs-logs-create.sql
+\i acs-metadata-create.sql
+\i acs-objects-create.sql
+\i acs-relationships-create.sql
+\i utilities-create.sql
+\i community-core-create.sql
+\i groups-create.sql
+\i rel-segments-create.sql
+\i rel-constraints-create.sql
+\i groups-body-create.sql
+\i rel-segments-body-create.sql
+\i acs-permissions-create.sql
+\i security-create.sql
+\i journal-create.sql
+\i site-nodes-create.sql
+\i apm-create.sql
+
+\i acs-create.sql
+--
+
+-- set feedback on
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-kernel-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-kernel-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-kernel-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,25 @@
+--
+-- /packages/acs-kernel/sql/acs-kernel-drop.sql
+--
+-- Purge the entire ACS Core package's data model
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @creation-date 2000/07/29
+-- @cvs-id acs-kernel-drop.sql,v 1.7.2.1 2001/01/12 22:52:29 oumi Exp
+--
+
+\i acs-drop.sql
+\i journal-drop.sql
+\i utilities-drop.sql
+\i security-drop.sql
+\i acs-permissions-drop.sql
+\i rel-constraints-drop.sql
+\i rel-segments-drop.sql
+\i groups-drop.sql
+\i site-nodes-drop.sql
+\i community-core-drop.sql
+\i acs-relationships-drop.sql
+\i acs-objects-drop.sql
+\i acs-metadata-drop.sql
+\i apm-drop.sql
+\i acs-logs-drop.sql
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-logs-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-logs-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-logs-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,119 @@
+--
+-- packages/acs-kernel/sql/acs-logs-create.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-10-02
+-- @cvs-id acs-logs-create.sql,v 1.6 2000/11/02 17:55:49 yon Exp
+--
+
+create sequence t_acs_log_id_seq;
+create view acs_log_id_seq as
+select nextval('t_acs_log_id_seq') as nextval;
+
+create table acs_logs (
+ log_id integer
+ constraint acs_logs_pk
+ primary key,
+ log_date timestamp default now() not null,
+ log_level varchar(20)
+ constraint acs_logs_log_level_ck
+ check (log_level in ('notice', 'warn', 'error',
+ 'debug')),
+ log_key varchar(100) not null,
+ message text not null
+);
+
+-- create or replace package acs_log
+-- as
+--
+-- procedure notice (
+-- log_key in acs_logs.log_key%TYPE,
+-- message in acs_logs.message%TYPE
+-- );
+--
+-- procedure warn (
+-- log_key in acs_logs.log_key%TYPE,
+-- message in acs_logs.message%TYPE
+-- );
+--
+-- procedure error (
+-- log_key in acs_logs.log_key%TYPE,
+-- message in acs_logs.message%TYPE
+-- );
+--
+-- procedure debug (
+-- log_key in acs_logs.log_key%TYPE,
+-- message in acs_logs.message%TYPE
+-- );
+--
+-- end;
+
+-- show errors
+
+-- create or replace package body acs_log
+-- procedure notice
+create function acs_log__notice (varchar,varchar)
+returns integer as '
+declare
+ notice__log_key alias for $1;
+ notice__message alias for $2;
+begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, ''notice'', notice__log_key, notice__message);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure warn
+create function acs_log__warn (varchar,varchar)
+returns integer as '
+declare
+ warn__log_key alias for $1;
+ warn__message alias for $2;
+begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, ''warn'', warn__log_key, warn__message);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure error
+create function acs_log__error (varchar,varchar)
+returns integer as '
+declare
+ error__log_key alias for $1;
+ error__message alias for $2;
+begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, ''error'', error__log_key, error__message);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure debug
+create function acs_log__debug (varchar,varchar)
+returns integer as '
+declare
+ debug__log_key alias for $1;
+ debug__message alias for $2;
+begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, ''debug'', debug__log_key, debug__message);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-logs-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-logs-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-logs-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,5 @@
+
+select drop_package('acs_log');
+drop table acs_logs;
+drop view acs_log_id_seq;
+drop sequence t_acs_log_id_seq;
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-metadata-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-metadata-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-metadata-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,824 @@
+--
+-- acs-kernel/sql/acs-metadata-create.sql
+--
+-- A generic metadata system that allows table inheritence. This is
+-- based in many ways on Problem Set 4 by Philip Greenspun
+-- (philg@mit.edu), and the user-groups data model by Tracy Adams
+-- (teadams@mit.edu).
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @author Rafael Schloming (rhs@mit.edu)
+-- @author Jon Salz (jsalz@mit.edu)
+--
+-- @creation-date 2000-05-18
+--
+-- @cvs-id acs-metadata-create.sql,v 1.9.2.8 2001/01/22 20:23:46 mbryzek Exp
+--
+
+-- ******************************************************************
+-- * KNOWLEDGE LEVEL
+-- ******************************************************************
+
+------------------
+-- OBJECT TYPES --
+------------------
+
+create table acs_object_types (
+ object_type varchar(100) not null
+ constraint acs_object_types_pk primary key,
+ supertype varchar(100) constraint acs_object_types_supertype_fk
+ references acs_object_types (object_type),
+ abstract_p boolean default 'f' not null,
+ pretty_name varchar(100) not null
+ constraint acs_obj_types_pretty_name_un
+ unique,
+ pretty_plural varchar(100) not null
+ constraint acs_obj_types_pretty_plural_un
+ unique,
+ table_name varchar(30) not null
+ constraint acs_object_types_tbl_name_un unique,
+ id_column varchar(30) not null,
+ package_name varchar(30) not null
+ constraint acs_object_types_pkg_name_un unique,
+ name_method varchar(30) default '' not null,
+ type_extension_table varchar(30) default '' not null,
+ dynamic_p boolean default 'f',
+ tree_sortkey varchar(4000)
+);
+
+create index acs_obj_types_supertype_idx on acs_object_types (supertype);
+create index acs_obj_types_tree_skey_idx on acs_object_types (tree_sortkey);
+
+-- support for tree queries on acs_object_types
+
+create function acs_object_type_insert_tr () returns opaque as '
+declare
+ v_parent_sk varchar;
+ max_key varchar;
+begin
+ select max(tree_sortkey) into max_key
+ from acs_object_types
+ where supertype = new.supertype;
+
+ select coalesce(max(tree_sortkey),'''') into v_parent_sk
+ from acs_object_types
+ where object_type = new.supertype;
+
+ new.tree_sortkey := v_parent_sk || ''/'' || tree_next_key(max_key);
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_object_type_insert_tr before insert
+on acs_object_types for each row
+execute procedure acs_object_type_insert_tr ();
+
+create function acs_object_type_update_tr () returns opaque as '
+declare
+ v_parent_sk varchar;
+ max_key varchar;
+ v_rec record;
+ clr_keys_p boolean default ''t'';
+begin
+ if new.object_type = old.object_type and
+ new.supertype = old.supertype then
+
+ return new;
+
+ end if;
+
+ for v_rec in select object_type
+ from acs_object_types
+ where tree_sortkey like new.tree_sortkey || ''%''
+ order by tree_sortkey
+ LOOP
+ if clr_keys_p then
+ update acs_object_types set tree_sortkey = null
+ where tree_sortkey like new.tree_sortkey || ''%'';
+ clr_keys_p := ''f'';
+ end if;
+
+ select max(tree_sortkey) into max_key
+ from acs_object_types
+ where supertype = (select supertype
+ from acs_object_types
+ where object_type = v_rec.object_type);
+
+ select coalesce(max(tree_sortkey),'''') into v_parent_sk
+ from acs_object_types
+ where object_type = (select supertype
+ from acs_object_types
+ where object_type = v_rec.object_type);
+
+ update acs_object_types
+ set tree_sortkey = v_parent_sk || ''/'' || tree_next_key(max_key)
+ where object_type = v_rec.object_type;
+
+ end LOOP;
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_object_type_update_tr after update
+on acs_object_types
+for each row
+execute procedure acs_object_type_update_tr ();
+
+comment on table acs_object_types is '
+ Each row in the acs_object_types table represents a distinct class
+ of objects. For each instance of any acs_object_type, there is a
+ corresponding row in the acs_objects table. Essentially,
+ acs_objects.object_id supersedes the on_which_table/on_what_id pair
+ that ACS 3.x used as the system-wide identifier for heterogeneous
+ objects. The value of having a system-wide identifier for
+ heterogeneous objects is that it helps us provide general solutions
+ for common problems like access control, workflow, categorppization,
+ and search. (Note that this framework is not overly restrictive,
+ because it doesn''t force every type of object to be represented in
+ the acs_object_types table.) Each acs_object_type has:
+ * Attributes (stored in the acs_attributes table)
+ Examples:
+ * the "user" object_type has "email" and "password" attributes
+ * the "content_item" object_type has "title" and "body" attributes
+ * Relationship types (stored in the acs_rel_types table)
+ Examples:
+ * "a team has one team leader who is a user" (in other words,
+ instances of the "team" object_type must have one "team leader"
+ relationship to an instance of the "user" object_type)
+ * "a content item may have zero or authors who are people or
+ organizations, i.e., parties" (in other words, instances of
+ the "content_item" object_type may have zero or more "author"
+ relationships to instances of the "party" object_type)
+ Possible extensions include automatic versioning, logical deletion,
+ and auditing.
+';
+
+comment on column acs_object_types.supertype is '
+ The object_type of which this object_type is a specialization (if
+ any). For example, the supertype of the "user" object_type is
+ "person". An object_type inherits the attributes and relationship
+ rules of its supertype, though it can add constraints to the
+ attributes and/or it can override the relationship rules. For
+ instance, the "person" object_type has an optional "email" attribute,
+ while its "user" subtype makes "email" mandatory.
+';
+
+comment on column acs_object_types.abstract_p is '
+ ...
+ If the object_type is not abstract, then all of its attributes must
+ have a non-null storage specified.
+';
+
+comment on column acs_object_types.table_name is '
+ The name of the type-specific table in which the values of attributes
+ specific to this object_type are stored, if any.
+';
+
+comment on column acs_object_types.id_column is '
+ The name of the primary key column in the table identified by
+ table_name.
+';
+
+comment on column acs_object_types.name_method is '
+ The name of a stored function that takes an object_id as an argument
+ and returns a varchar2: the corresponding object name. This column is
+ required to implement the polymorphic behavior of the acs.object_name()
+ function.
+';
+
+comment on column acs_object_types.type_extension_table is '
+ Object types (and their subtypes) that require more type-specific
+ data than the fields already existing in acs_object_types may name
+ a table in which that data is stored. The table should be keyed
+ by the associated object_type. For example, a row in the user_group_types
+ table stores a default approval policy for every user group of that type.
+ In this example, the user_group_types table has a primary key named
+ group_type that references acs_object_types. If a subtype of user_groups
+ for example, lab_courses, has its own type-specific data, it could be
+ maintained in a table called lab_course_types, with a primary key named
+ lab_course_type that references user_group_types. This provides the same
+ functionality as static class fields in an object-oriented programming language.
+';
+
+
+comment on column acs_object_types.dynamic_p is '
+ This flag is used to identify object types created dynamically
+ (e.g. through a web interface). Dynamically created object types can
+ be administered differently. For example, the group type admin pages
+ only allow users to add attributes or otherwise modify dynamic
+ object types. This column is still experimental and may not be supported in the
+ future. That is the reason it is not yet part of the API.
+';
+
+-- create view acs_object_type_supertype_map
+-- as select ot.object_type, ota.object_type as ancestor_type
+-- from acs_object_types ot, acs_object_types ota
+-- where ota.object_type in (select object_type
+-- from acs_object_types
+-- start with object_type = ot.supertype
+-- connect by object_type = prior supertype);
+
+create view acs_object_type_supertype_map
+as select ot.object_type, ota.object_type as ancestor_type
+ from acs_object_types ot, acs_object_types ota
+ where ota.object_type in (select ot2.object_type
+ from acs_object_types ot1,
+ acs_object_types ot2
+ where o1.object_type = ot.supertype
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%'));
+
+
+create table acs_object_type_tables (
+ object_type varchar(100) not null
+ constraint acs_obj_type_tbls_obj_type_fk
+ references acs_object_types (object_type),
+ table_name varchar(30) not null,
+ id_column varchar(30) default '' not null,
+ constraint acs_object_type_tables_pk
+ primary key (object_type, table_name)
+);
+
+create index acs_objtype_tbls_objtype_idx on acs_object_type_tables (object_type);
+
+comment on table acs_object_type_tables is '
+ This table is used for objects that want to vertically partition
+ their data storage, for example user_demographics stores a set of
+ optional columns that belong to a user object.
+';
+
+comment on column acs_object_type_tables.id_column is '
+ If this is null then the id column is assumed to have the same name
+ as the primary table.
+';
+
+------------------------------------
+-- DATATYPES AND ATTRIBUTES --
+------------------------------------
+
+create table acs_datatypes (
+ datatype varchar(50) not null
+ constraint acs_datatypes_pk primary key,
+ max_n_values integer default 1
+ constraint acs_datatypes_max_n_ck
+ check (max_n_values > 0)
+);
+
+comment on table acs_datatypes is '
+ Defines the set of available datatypes for acs_attributes. These
+ datatypes are abstract, not implementation-specific, i.e., they
+ are not Oracle datatypes. The set of pre-defined datatypes is
+ inspired by XForms (http://www.w3.org/TR/xforms-datamodel/).
+';
+
+comment on column acs_datatypes.max_n_values is '
+ The maximum number of values that any attribute with this datatype
+ can have. Of the predefined attribute types, only "boolean" specifies
+ a non-null max_n_values, because it doesn''t make sense to have a
+ boolean attribute with more than one value. There is no
+ corresponding min_n_values column, because each attribute may be
+ optional, i.e., min_n_values would always be zero.
+';
+
+-- Load pre-defined datatypes.
+--
+create function inline_0 ()
+returns integer as '
+begin
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''string'', null);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''boolean'', 1);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''number'', null);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''integer'', 1);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''money'', null);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''date'', null);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''timestamp'', null);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''time_of_day'', null);
+
+ insert into acs_datatypes
+ (datatype, max_n_values)
+ values
+ (''enumeration'', null);
+
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+
+--create table acs_input_types (
+--);
+
+create sequence t_acs_attribute_id_seq;
+create view acs_attribute_id_seq as
+select nextval('t_acs_attribute_id_seq') as nextval;
+
+create table acs_attributes (
+ attribute_id integer not null
+ constraint acs_attributes_pk
+ primary key,
+ object_type varchar(100) not null
+ constraint acs_attributes_object_type_fk
+ references acs_object_types (object_type),
+ table_name varchar(30),
+ constraint acs_attrs_obj_type_tbl_name_fk
+ foreign key (object_type, table_name)
+ references acs_object_type_tables,
+ attribute_name varchar(100) not null,
+ pretty_name varchar(100) not null,
+ pretty_plural varchar(100) default '' not null,
+ sort_order integer not null,
+ datatype varchar(50) not null
+ constraint acs_attributes_datatype_fk
+ references acs_datatypes (datatype),
+ default_value text default '' not null,
+ min_n_values integer default 1 not null
+ constraint acs_attributes_min_n_ck
+ check (min_n_values >= 0),
+ max_n_values integer default 1 not null
+ constraint acs_attributes_max_n_ck
+ check (max_n_values >= 0),
+ storage varchar(13) default 'type_specific'
+ constraint acs_attributes_storage_ck
+ check (storage in ('type_specific',
+ 'generic')),
+ static_p boolean default 'f',
+ column_name varchar(30) default '' not null,
+ constraint acs_attributes_attr_name_un
+ unique (attribute_name, object_type),
+ constraint acs_attributes_pretty_name_un
+ unique (pretty_name, object_type),
+ constraint acs_attributes_sort_order_un
+ unique (attribute_id, sort_order),
+ constraint acs_attributes_n_values_ck
+ check (min_n_values <= max_n_values)
+);
+-- constraint acs_attrs_pretty_plural_un
+-- unique (pretty_plural, object_type),
+
+create index acs_attrs_obj_type_idx on acs_attributes (object_type);
+create index acs_attrs_tbl_name_idx on acs_attributes (table_name);
+create index acs_attrs_datatype_idx on acs_attributes (datatype);
+
+comment on table acs_attributes is '
+ Each row in the acs_attributes
table defines an
+ attribute of the specified object type. Each object of this type
+ must have a minimum of min_n_values values and a maximum of
+ max_n_values for this attribute.
+';
+
+comment on column acs_attributes.table_name is '
+ If the data storage for the object type is arranged in a vertically
+ partitioned manner, then this column should indicate in which table
+ the attribute is stored.
+';
+
+comment on column acs_attributes.storage is '
+ Indicates how values of this attribute are stored: either
+ "type_specific" (i.e., in the table identified by
+ object_type.table_name) or "generic" (i.e., in the
+ acs_attribute_values table). (Or we could just have a column_name and,
+ if it''s null, then assume that we''re using acs_attribute_values.)
+';
+
+comment on column acs_attributes.static_p is '
+ Determines whether this attribute is static. If so, only one copy of
+ the attribute''s value exists for all objects of the same type. This
+ value is stored in acs_static_attr_values table if storage_type is
+ "generic". Otherwise, each object of this type can have its own
+ distinct value for the attribute.
+';
+
+comment on column acs_attributes.column_name is '
+ If storage is "type_specific", column_name identifies the column in
+ the table identified by object_type.table_name that holds the values
+ of this attribute. If column_name is null, then we assume that
+ attribute_name identifies a column in the table identified by
+ object_type.table_name.
+';
+
+create table acs_enum_values (
+ attribute_id integer not null
+ constraint asc_enum_values_attr_id_fk
+ references acs_attributes (attribute_id),
+ enum_value varchar(1000) default '' not null,
+ pretty_name varchar(100) not null,
+ sort_order integer not null,
+ constraint acs_enum_values_pk
+ primary key (attribute_id, enum_value),
+ constraint acs_enum_values_pretty_name_un
+ unique (attribute_id, pretty_name),
+ constraint acs_enum_values_sort_order_un
+ unique (attribute_id, sort_order)
+);
+
+create index acs_enum_values_attr_id_idx on acs_enum_values (attribute_id);
+
+create table acs_attribute_descriptions (
+ object_type varchar(100) not null constraint acs_attr_descs_obj_type_fk
+ references acs_object_types (object_type),
+ attribute_name varchar(100) not null,
+ constraint acs_attr_descs_ob_tp_at_na_fk
+ foreign key (object_type, attribute_name)
+ references acs_attributes (object_type, attribute_name),
+ description_key varchar(100) default '' not null,
+ constraint acs_attribute_descriptions_pk
+ primary key (object_type, attribute_name, description_key),
+ description text not null
+);
+
+create index acs_attr_desc_obj_type_idx on acs_attribute_descriptions (object_type);
+create index acs_attr_desc_attr_name_idx on acs_attribute_descriptions (attribute_name);
+
+
+-- Create a view to show us all the attributes for one object,
+-- including attributes for each of its supertypes
+
+-- Note that the internal union is required to get attributes for the
+-- object type we specify. Without this union, we would get attributes
+-- for all supertypes, but not for the specific type in question
+
+-- Note also that we cannot select attr.* in the view because the
+-- object_type in the attributes table refers to one attribute (kind
+-- of like the owner of the attribute). That object_type is really the
+-- ancestor type... that is, the ancestor of the user-specified object
+-- type for which the attribute should be specified.
+
+create view acs_object_type_attributes as
+select all_types.object_type, all_types.ancestor_type,
+ attr.attribute_id, attr.table_name, attr.attribute_name,
+ attr.pretty_name, attr.pretty_plural, attr.sort_order,
+ attr.datatype, attr.default_value, attr.min_n_values,
+ attr.max_n_values, attr.storage, attr.static_p, attr.column_name
+from acs_attributes attr,
+ (select map.object_type, map.ancestor_type
+ from acs_object_type_supertype_map map, acs_object_types t
+ where map.object_type=t.object_type
+ UNION ALL
+ select t.object_type, t.object_type as ancestor_type
+ from acs_object_types t) all_types
+where attr.object_type = all_types.ancestor_type;
+
+
+-----------------------
+-- METADATA PACKAGES --
+-----------------------
+
+-- create or replace package acs_object_type
+-- is
+-- -- define an object type
+-- procedure create_type (
+-- object_type in acs_object_types.object_type%TYPE,
+-- pretty_name in acs_object_types.pretty_name%TYPE,
+-- pretty_plural in acs_object_types.pretty_plural%TYPE,
+-- supertype in acs_object_types.supertype%TYPE
+-- default 'acs_object',
+-- table_name in acs_object_types.table_name%TYPE,
+-- id_column in acs_object_types.id_column%TYPE default 'XXX',
+-- package_name in acs_object_types.package_name%TYPE default null,
+-- abstract_p in acs_object_types.abstract_p%TYPE default 'f',
+-- type_extension_table in acs_object_types.type_extension_table%TYPE
+-- default null,
+-- name_method in acs_object_types.name_method%TYPE default null
+-- );
+--
+-- -- delete an object type definition
+-- procedure drop_type (
+-- object_type in acs_object_types.object_type%TYPE,
+-- cascade_p in char default 'f'
+-- );
+--
+-- -- look up an object type's pretty_name
+-- function pretty_name (
+-- object_type in acs_object_types.object_type%TYPE
+-- ) return acs_object_types.pretty_name%TYPE;
+--
+-- -- Returns 't' if object_type_2 is a subtype of object_type_1. Note
+-- -- that this function will return 'f' if object_type_1 =
+-- -- object_type_2
+-- function is_subtype_p (
+-- object_type_1 in acs_object_types.object_type%TYPE,
+-- object_type_2 in acs_object_types.object_type%TYPE
+-- ) return char;
+--
+-- end acs_object_type;
+
+-- show errors
+
+
+-- create or replace package acs_attribute
+-- is
+--
+-- -- define an object attribute
+-- function create_attribute (
+-- object_type in acs_attributes.object_type%TYPE,
+-- attribute_name in acs_attributes.attribute_name%TYPE,
+-- datatype in acs_attributes.datatype%TYPE,
+-- pretty_name in acs_attributes.pretty_name%TYPE,
+-- pretty_plural in acs_attributes.pretty_plural%TYPE default null,
+-- table_name in acs_attributes.table_name%TYPE default null,
+-- column_name in acs_attributes.column_name%TYPE default null,
+-- default_value in acs_attributes.default_value%TYPE default null,
+-- min_n_values in acs_attributes.min_n_values%TYPE default 1,
+-- max_n_values in acs_attributes.max_n_values%TYPE default 1,
+-- sort_order in acs_attributes.sort_order%TYPE default null,
+-- storage in acs_attributes.storage%TYPE default 'type_specific',
+-- static_p in acs_attributes.static_p%TYPE default 'f'
+-- ) return acs_attributes.attribute_id%TYPE;
+--
+-- procedure drop_attribute (
+-- object_type in varchar2,
+-- attribute_name in varchar2
+-- );
+--
+-- procedure add_description (
+-- object_type in acs_attribute_descriptions.object_type%TYPE,
+-- attribute_name in acs_attribute_descriptions.attribute_name%TYPE,
+-- description_key in acs_attribute_descriptions.description_key%TYPE,
+-- description in acs_attribute_descriptions.description%TYPE
+-- );
+--
+-- procedure drop_description (
+-- object_type in acs_attribute_descriptions.object_type%TYPE,
+-- attribute_name in acs_attribute_descriptions.attribute_name%TYPE,
+-- description_key in acs_attribute_descriptions.description_key%TYPE
+-- );
+--
+-- end acs_attribute;
+
+-- show errors
+
+
+-- create or replace package body acs_object_type
+-- procedure create_type
+create function acs_object_type__create_type (varchar,varchar,varchar,varchar,varchar,varchar,varchar,boolean,varchar,varchar)
+returns integer as '
+declare
+ create_type__object_type alias for $1;
+ create_type__pretty_name alias for $2;
+ create_type__pretty_plural alias for $3;
+ create_type__supertype alias for $4;
+ create_type__table_name alias for $5;
+ create_type__id_column alias for $6;
+ create_type__package_name alias for $7;
+ create_type__abstract_p alias for $8;
+ create_type__type_extension_table alias for $9;
+ create_type__name_method alias for $10;
+ v_package_name acs_object_types.package_name%TYPE;
+ v_name_method varchar;
+ v_idx integer;
+begin
+ v_idx := position(''.'' in create_type__name_method);
+ if v_idx <> 0 then
+ v_name_method := substr(create_type__name_method,1,v_idx - 1) || ''__'' || substr(create_type__name_method, v_idx + 1);
+ else
+ v_name_method := create_type__name_method;
+ end if;
+
+ if create_type__package_name is null then
+ v_package_name := create_type__object_type;
+ else
+ v_package_name := create_type__package_name;
+ end if;
+
+ insert into acs_object_types
+ (object_type, pretty_name, pretty_plural, supertype, table_name,
+ id_column, abstract_p, type_extension_table, package_name,
+ name_method)
+ values
+ (create_type__object_type, create_type__pretty_name,
+ create_type__pretty_plural, create_type__supertype,
+ create_type__table_name, create_type__id_column,
+ create_type__abstract_p, coalesce(create_type__type_extension_table,''''),
+ v_package_name, coalesce(v_name_method,''''));
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure drop_type
+create function acs_object_type__drop_type (varchar,boolean)
+returns integer as '
+declare
+ drop_type__object_type alias for $1;
+ drop_type__cascade_p alias for $2;
+ row record;
+begin
+
+ -- drop all the attributes associated with this type
+ for row in select attribute_name
+ from acs_attributes
+ where object_type = drop_type__object_type
+ loop
+ PERFORM acs_attribute__drop_attribute (drop_type__object_type, row.attribute_name);
+ end loop;
+
+ delete from acs_attributes
+ where object_type = drop_type__object_type;
+
+ delete from acs_object_types
+ where object_type = drop_type__object_type;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function pretty_name
+create function acs_object_type__pretty_name (varchar)
+returns varchar as '
+declare
+ pretty_name__object_type alias for $1;
+ v_pretty_name acs_object_types.pretty_name%TYPE;
+begin
+ select t.pretty_name into v_pretty_name
+ from acs_object_types t
+ where t.object_type = pretty_name__object_type;
+
+ return v_pretty_name;
+
+end;' language 'plpgsql';
+
+
+-- function is_subtype_p
+create function acs_object_type__is_subtype_p (varchar,varchar)
+returns boolean as '
+declare
+ is_subtype_p__object_type_1 alias for $1;
+ is_subtype_p__object_type_2 alias for $2;
+ v_result integer;
+begin
+ -- select count(*) into v_result
+ -- where exists (select 1
+ -- from acs_object_types t
+ -- where t.object_type = is_subtype_p__object_type_2
+ -- connect by prior t.object_type = t.supertype
+ -- start with t.supertype = is_subtype_p__object_type_1);
+ select count(*)
+ where exists (select 1
+ from acs_object_types t
+ where t.object_type = is_subtype_p__object_type_2
+ and tree_sortkey like (select tree_sortkey || '%'
+ from acs_object_types
+ where object_type = is_subtype_p__object_type_1 ));
+
+ if v_result > 0 then
+ return ''t'';
+ end if;
+
+ return ''f'';
+
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
+
+
+-- create or replace package body acs_attribute
+-- function create_attribute
+create function acs_attribute__create_attribute (varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,integer,varchar,boolean)
+returns integer as '
+declare
+ create_attribute__object_type alias for $1;
+ create_attribute__attribute_name alias for $2;
+ create_attribute__datatype alias for $3;
+ create_attribute__pretty_name alias for $4;
+ create_attribute__pretty_plural alias for $5;
+ create_attribute__table_name alias for $6;
+ create_attribute__column_name alias for $7;
+ create_attribute__default_value alias for $8;
+ create_attribute__min_n_values alias for $9;
+ create_attribute__max_n_values alias for $10;
+ create_attribute__sort_order alias for $11;
+ create_attribute__storage alias for $12;
+ create_attribute__static_p alias for $13;
+
+ v_sort_order acs_attributes.sort_order%TYPE;
+ v_attribute_id acs_attributes.attribute_id%TYPE;
+begin
+ if create_attribute__sort_order is null then
+ select coalesce(max(sort_order), 1) into v_sort_order
+ from acs_attributes
+ where object_type = create_attribute__object_type
+ and attribute_name = create_attribute__attribute_name;
+ else
+ v_sort_order := create_attribute__sort_order;
+ end if;
+
+ select acs_attribute_id_seq.nextval into v_attribute_id;
+
+ insert into acs_attributes
+ (attribute_id, object_type, table_name, column_name, attribute_name,
+ pretty_name, pretty_plural, sort_order, datatype, default_value,
+ min_n_values, max_n_values, storage, static_p)
+ values
+ (v_attribute_id, create_attribute__object_type,
+ create_attribute__table_name, coalesce(create_attribute__column_name,''''),
+ create_attribute__attribute_name, create_attribute__pretty_name,
+ coalesce(create_attribute__pretty_plural,''''), v_sort_order,
+ create_attribute__datatype, coalesce(create_attribute__default_value,''''),
+ create_attribute__min_n_values, create_attribute__max_n_values,
+ create_attribute__storage, create_attribute__static_p);
+
+ return v_attribute_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure drop_attribute
+create function acs_attribute__drop_attribute (varchar,varchar)
+returns integer as '
+declare
+ drop_attribute__object_type alias for $1;
+ drop_attribute__attribute_name alias for $2;
+begin
+ -- first remove possible values for the enumeration
+ delete from acs_enum_values
+ where attribute_id in (select a.attribute_id
+ from acs_attributes a
+ where a.object_type = drop_attribute__object_type
+ and a.attribute_name = drop_attribute__attribute_name);
+
+ delete from acs_attributes
+ where object_type = drop_attribute__object_type
+ and attribute_name = drop_attribute__attribute_name;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure add_description
+create function acs_attribute__add_description (varchar,varchar,varchar,text)
+returns integer as '
+declare
+ add_description__object_type alias for $1;
+ add_description__attribute_name alias for $2;
+ add_description__description_key alias for $3;
+ add_description__description alias for $4;
+begin
+ insert into acs_attribute_descriptions
+ (object_type, attribute_name, description_key, description)
+ values
+ (add_description__object_type, add_description__attribute_name,
+ coalesce(add_description__description_key,''''), add_description__description);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure drop_description
+create function acs_attribute__drop_description (varchar,varchar,varchar)
+returns integer as '
+declare
+ drop_description__object_type alias for $1;
+ drop_description__attribute_name alias for $2;
+ drop_description__description_key alias for $3;
+begin
+ delete from acs_attribute_descriptions
+ where object_type = drop_description__object_type
+ and attribute_name = drop_description__attribute_name
+ and description_key = drop_description__description_key;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-metadata-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-metadata-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-metadata-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,23 @@
+--
+-- acs-kernel/sql/acs-metadata-drop.sql
+--
+-- DDL commands to purge the Community Core data model
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @creation-date 2000-05-18
+-- @cvs-id acs-metadata-drop.sql,v 1.5.2.1 2001/01/12 23:05:13 oumi Exp
+--
+\t
+select drop_package('acs_attribute');
+select drop_package('acs_object_type');
+\t
+drop view acs_object_type_attributes;
+drop table acs_attribute_descriptions;
+drop table acs_enum_values;
+drop table acs_attributes;
+drop view acs_attribute_id_seq;
+drop sequence t_acs_attribute_id_seq;
+drop table acs_datatypes;
+drop table acs_object_type_tables;
+drop view acs_object_type_supertype_map;
+drop table acs_object_types;
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,1240 @@
+--
+-- acs-kernel/sql/acs-objects-create.sql
+--
+-- A base object type that provides auditing columns, permissioning,
+-- attributes, and relationships to any subtypes.
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @author Rafael Schloming (rhs@mit.edu)
+-- @author Jon Salz (jsalz@mit.edu)
+--
+-- @creation-date 2000-05-18
+--
+-- @cvs-id acs-objects-create.sql,v 1.15.2.2 2001/01/12 22:54:24 oumi Exp
+--
+
+-----------------------------
+-- PREDEFINED OBJECT TYPES --
+-----------------------------
+
+create function inline_0 ()
+returns integer as '
+declare
+ attr_id acs_attributes.attribute_id%TYPE;
+begin
+ --
+ -- The ultimate supertype: object
+ --
+ PERFORM acs_object_type__create_type (
+ ''acs_object'',
+ ''Object'',
+ ''Objects'',
+ null,
+ ''acs_objects'',
+ ''object_id'',
+ ''acs_object'',
+ ''f'',
+ null,
+ ''acs_object.default_name''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''object_type'',
+ ''string'',
+ ''Object Type'',
+ ''Object Types'',
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''creation_date'',
+ ''date'',
+ ''Created Date'',
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''creation_ip'',
+ ''string'',
+ ''Creation IP Address'',
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''last_modified'',
+ ''date'',
+ ''Last Modified On'',
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''modifying_ip'',
+ ''string'',
+ ''Modifying IP Address'',
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''creation_user'',
+ ''integer'',
+ ''Creation user'',
+ ''Creation users'',
+ null,
+ null,
+ null,
+ 0,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ attr_id := acs_attribute__create_attribute (
+ ''acs_object'',
+ ''context_id'',
+ ''integer'',
+ ''Context ID'',
+ ''Context IDs'',
+ null,
+ null,
+ null,
+ 0,
+ 1,
+ null,
+ ''type_specific'',
+ ''f''
+ );
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
+
+-- ******************************************************************
+-- * OPERATIONAL LEVEL
+-- ******************************************************************
+
+-------------
+-- OBJECTS --
+-------------
+
+create sequence t_acs_object_id_seq;
+create view acs_object_id_seq as
+select nextval('t_acs_object_id_seq') as nextval;
+
+create table acs_objects (
+ object_id integer not null
+ constraint acs_objects_pk primary key,
+ object_type varchar(100) not null
+ constraint acs_objects_object_type_fk
+ references acs_object_types (object_type),
+ context_id integer constraint acs_objects_context_id_fk
+ references acs_objects(object_id),
+ security_inherit_p boolean default 't' not null,
+ creation_user integer,
+ creation_date timestamp default now() not null,
+ creation_ip varchar(50) default '' not null,
+ last_modified timestamp default now() not null,
+ modifying_user integer,
+ modifying_ip varchar(50) default '' not null,
+ constraint acs_objects_context_object_un
+ unique (context_id, object_id)
+);
+
+create index acs_objects_context_object_idx on
+ acs_objects (context_id, object_id);
+
+-- alter table acs_objects modify constraint acs_objects_context_object_un enable;
+
+create index acs_objects_creation_user_idx on acs_objects (creation_user);
+create index acs_objects_modify_user_idx on acs_objects (modifying_user);
+
+create index acs_objects_object_type_idx on acs_objects (object_type);
+
+create function acs_objects_mod_ip_insert_tr () returns opaque as '
+begin
+ new.modifying_ip := new.creation_ip;
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_objects_mod_ip_insert_tr before insert on acs_objects
+for each row execute procedure acs_objects_mod_ip_insert_tr ();
+
+-- show errors
+
+create function acs_objects_last_mod_update_tr () returns opaque as '
+begin
+ new.last_modified := now();
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_objects_last_mod_update_tr before update on acs_objects
+for each row execute procedure acs_objects_last_mod_update_tr ();
+
+-- show errors
+
+comment on table acs_objects is '
+';
+
+comment on column acs_objects.context_id is '
+ The context_id column points to an object that provides a context for
+ this object. Often this will reflect an observed hierarchy in a site,
+ for example a bboard message would probably list a bboard topic as
+ it''s context, and a bboard topic might list a sub-site as it''s
+ context. Whenever we ask a question of the form "can user X perform
+ action Y on object Z", the acs security model will defer to an
+ object''s context if there is no information about user X''s
+ permission to perform action Y on object Z.
+';
+
+comment on column acs_objects.creation_user is '
+ Who created the object; may be null since objects can be created by
+ automated processes
+';
+
+comment on column acs_objects.modifying_user is '
+ Who last modified the object
+';
+
+-----------------------
+-- CONTEXT HIERARCHY --
+-----------------------
+
+create table acs_object_context_index (
+ object_id integer not null
+ constraint acs_obj_context_idx_obj_id_fk
+ references acs_objects(object_id),
+ ancestor_id integer not null
+ constraint acs_obj_context_idx_anc_id_fk
+ references acs_objects(object_id),
+ n_generations integer not null
+ constraint acs_obj_context_idx_n_gen_ck
+ check (n_generations >= 0),
+ constraint acs_object_context_index_pk
+ primary key (object_id, ancestor_id)
+);
+
+create index acs_obj_ctx_idx_ancestor_idx on acs_object_context_index (ancestor_id);
+
+create view acs_object_paths
+as select object_id, ancestor_id, n_generations
+ from acs_object_context_index;
+
+create view acs_object_contexts
+as select object_id, ancestor_id, n_generations
+ from acs_object_context_index
+ where object_id != ancestor_id;
+
+create function acs_objects_context_id_in_tr () returns opaque as '
+begin
+ insert into acs_object_context_index
+ (object_id, ancestor_id, n_generations)
+ values
+ (new.object_id, new.object_id, 0);
+
+ if new.context_id is not null and new.security_inherit_p = ''t'' then
+ insert into acs_object_context_index
+ (object_id, ancestor_id, n_generations)
+ select
+ new.object_id as object_id, ancestor_id,
+ n_generations + 1 as n_generations
+ from acs_object_context_index
+ where object_id = new.context_id;
+ else if new.object_id != 0 then
+ -- 0 is the id of the security context root object
+ insert into acs_object_context_index
+ (object_id, ancestor_id, n_generations)
+ values
+ (new.object_id, 0, 1);
+ end if; end if;
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_objects_context_id_in_tr after insert on acs_objects
+for each row execute procedure acs_objects_context_id_in_tr ();
+
+-- show errors
+
+create function acs_objects_context_id_up_tr () returns opaque as '
+declare
+ pair record;
+begin
+ if new.object_id = old.object_id and
+ new.context_id = old.context_id and
+ new.security_inherit_p = old.security_inherit_p then
+ return;
+ end if;
+
+ -- Remove my old ancestors from my descendants.
+ delete from acs_object_context_index
+ where object_id in (select object_id
+ from acs_object_contexts
+ where ancestor_id = old.object_id)
+ and ancestor_id in (select ancestor_id
+ from acs_object_contexts
+ where object_id = old.object_id);
+
+ -- Kill all my old ancestors.
+ delete from acs_object_context_index
+ where object_id = old.object_id;
+
+ insert into acs_object_context_index
+ (object_id, ancestor_id, n_generations)
+ values
+ (new.object_id, new.object_id, 0);
+
+ if new.context_id is not null and new.security_inherit_p = ''t'' then
+ -- Now insert my new ancestors for my descendants.
+ for pair in (select *
+ from acs_object_context_index
+ where ancestor_id = new.object_id) loop
+ insert into acs_object_context_index
+ (object_id, ancestor_id, n_generations)
+ select
+ pair.object_id, ancestor_id,
+ n_generations + pair.n_generations + 1 as n_generations
+ from acs_object_context_index
+ where object_id = new.context_id;
+ end loop;
+ else if new.object_id != 0 then
+ -- We need to make sure that new.OBJECT_ID and all of its
+ -- children have 0 as an ancestor.
+ for pair in (select *
+ from acs_object_context_index
+ where ancestor_id = new.object_id) loop
+ insert into acs_object_context_index
+ (object_id, ancestor_id, n_generations)
+ values
+ (pair.object_id, 0, pair.n_generations + 1);
+ end loop;
+ end if; end if;
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_objects_context_id_up_tr after update on acs_objects
+for each row execute procedure acs_objects_context_id_up_tr ();
+
+-- show errors
+
+create function acs_objects_context_id_del_tr () returns opaque as '
+begin
+ delete from acs_object_context_index
+ where object_id = old.object_id;
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger acs_objects_context_id_del_tr before delete on acs_objects
+for each row execute procedure acs_objects_context_id_del_tr ();
+
+-- show errors
+
+----------------------
+-- ATTRIBUTE VALUES --
+----------------------
+
+create sequence t_acs_attribute_value_id_seq;
+create view acs_attribute_value_id_seq as
+select nextval('t_acs_attribute_value_id_seq') as nextval;
+
+create table acs_attribute_values (
+ object_id integer not null
+ constraint acs_attr_values_obj_id_fk
+ references acs_objects (object_id) on delete cascade,
+ attribute_id integer not null
+ constraint acs_attr_values_attr_id_fk
+ references acs_attributes (attribute_id),
+ attr_value text default '' not null,
+ constraint acs_attribute_values_pk primary key
+ (object_id, attribute_id)
+);
+
+create index acs_attr_values_attr_id_idx on acs_attribute_values (attribute_id);
+
+comment on table acs_attribute_values is '
+ Instead of coercing everything into a big string, we could use
+ a "union", i.e, a string column, a number column, a date column,
+ and a discriminator.
+';
+
+create table acs_static_attr_values (
+ object_type varchar(100) not null
+ constraint acs_static_a_v_obj_id_fk
+ references acs_object_types (object_type) on delete cascade,
+ attribute_id integer not null
+ constraint acs_static_a_v_attr_id_fk
+ references acs_attributes (attribute_id),
+ attr_value text default '' not null,
+ constraint acs_static_a_v_pk primary key
+ (object_type, attribute_id)
+);
+
+create index acs_stat_attrs_attr_id_idx on acs_static_attr_values (attribute_id);
+
+comment on table acs_static_attr_values is '
+ Stores static values for the object attributes. One row per object
+ type.
+';
+
+------------------------
+-- ACS_OBJECT PACKAGE --
+------------------------
+
+-- create or replace package acs_object
+-- as
+--
+-- function new (
+-- object_id in acs_objects.object_id%TYPE default null,
+-- object_type in acs_objects.object_type%TYPE
+-- default 'acs_object',
+-- creation_date in acs_objects.creation_date%TYPE
+-- default sysdate,
+-- creation_user in acs_objects.creation_user%TYPE
+-- default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null,
+-- context_id in acs_objects.context_id%TYPE default null
+-- ) return acs_objects.object_id%TYPE;
+--
+-- procedure delete (
+-- object_id in acs_objects.object_id%TYPE
+-- );
+--
+-- function name (
+-- object_id in acs_objects.object_id%TYPE
+-- ) return varchar2;
+--
+-- -- The acs_object_types.name_method for "acs_object"
+-- --
+-- function default_name (
+-- object_id in acs_objects.object_id%TYPE
+-- ) return varchar2;
+--
+-- -- Determine where the attribute is stored and what sql needs to be
+-- -- in the where clause to retreive it
+-- -- Used in get_attribute and set_attribute
+-- procedure get_attribute_storage (
+-- object_id_in in acs_objects.object_id%TYPE,
+-- attribute_name_in in acs_attributes.attribute_name%TYPE,
+-- v_column out varchar2,
+-- v_table_name out varchar2,
+-- v_key_sql out varchar2
+-- );
+--
+-- -- Get/set the value of an object attribute, as long as
+-- -- the type can be cast to varchar2
+-- function get_attribute (
+-- object_id_in in acs_objects.object_id%TYPE,
+-- attribute_name_in in acs_attributes.attribute_name%TYPE
+-- ) return varchar2;
+--
+-- procedure set_attribute (
+-- object_id_in in acs_objects.object_id%TYPE,
+-- attribute_name_in in acs_attributes.attribute_name%TYPE,
+-- value_in in varchar2
+-- );
+--
+-- function check_representation (
+-- object_id in acs_objects.object_id%TYPE
+-- ) return char;
+--
+-- end acs_object;
+
+-- show errors
+
+-- create or replace package body acs_object
+-- procedure initialize_attributes
+create function acs_object__initialize_attributes (integer)
+returns integer as '
+declare
+ initialize_attributes__object_id alias for $1;
+ v_object_type acs_objects.object_type%TYPE;
+begin
+ -- XXX This should be fixed to initialize supertypes properly.
+
+ -- Initialize dynamic attributes
+ insert into acs_attribute_values
+ (object_id, attribute_id, attr_value)
+ select
+ initialize_attributes__object_id, a.attribute_id, a.default_value
+ from acs_attributes a, acs_objects o
+ where a.object_type = o.object_type
+ and o.object_id = initialize_attributes__object_id
+ and a.storage = ''generic''
+ and a.static_p = ''f'';
+
+ -- Retreive type for static attributes
+ select object_type into v_object_type from acs_objects
+ where object_id = initialize_attributes__object_id;
+
+ -- Initialize static attributes
+ -- begin
+ insert into acs_static_attr_values
+ (object_type, attribute_id, attr_value)
+ select
+ v_object_type, a.attribute_id, a.default_value
+ from acs_attributes a, acs_objects o
+ where a.object_type = o.object_type
+ and o.object_id = initialize_attributes__object_id
+ and a.storage = ''generic''
+ and a.static_p = ''t''
+ and not exists (select 1 from acs_static_attr_values
+ where object_type = a.object_type);
+ -- exception when no_data_found then null;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function new
+create function acs_object__new (integer,varchar,timestamp,integer,varchar,integer)
+returns integer as '
+declare
+ new__object_id alias for $1;
+ new__object_type alias for $2;
+ new__creation_date alias for $3;
+ new__creation_user alias for $4;
+ new__creation_ip alias for $5;
+ new__context_id alias for $6;
+ v_object_id acs_objects.object_id%TYPE;
+begin
+ if new__object_id is null then
+ select acs_object_id_seq.nextval
+ into v_object_id from dual;
+ else
+ v_object_id := new__object_id;
+ end if;
+
+ insert into acs_objects
+ (object_id, object_type, context_id,
+ creation_date, creation_user, creation_ip)
+ values
+ (v_object_id, new__object_type, new__context_id,
+ new__creation_date, new__creation_user, coalesce(new__creation_ip,''''));
+
+ PERFORM acs_object__initialize_attributes(v_object_id);
+
+ return v_object_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure delete
+create function acs_object__delete (integer)
+returns integer as '
+declare
+ delete__object_id alias for $1;
+ obj_type record;
+begin
+
+ -- Delete dynamic/generic attributes
+ delete from acs_attribute_values where object_id = delete__object_id;
+
+ -- select table_name, id_column
+ -- from acs_object_types
+ -- start with object_type = (select object_type
+ -- from acs_objects o
+ -- where o.object_id = delete__object_id)
+ -- connect by object_type = prior supertype
+
+ for obj_type
+ in (select table_name, id_column
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = (select object_type
+ from acs_objects o
+ where o.object_id = delete__object_id)
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%')
+ order by tree_sortkey desc)
+ loop
+ -- Delete from the table.
+ execute ''delete from '' || quote_ident(obj_type.table_name) ||
+ '' where '' || quote_ident(obj_type.id_column) || '' = '' || delete__object_id;
+ end loop;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function name
+create function acs_object__name (integer)
+returns varchar as '
+declare
+ name__object_id alias for $1;
+ object_name varchar(500);
+ v_object_id integer;
+ obj_type record;
+ obj record;
+begin
+ -- Find the name function for this object, which is stored in the
+ -- name_method column of acs_object_types. Starting with this
+ -- object''s actual type, traverse the type hierarchy upwards until
+ -- a non-null name_method value is found.
+ --
+ -- select name_method
+ -- from acs_object_types
+ -- start with object_type = (select object_type
+ -- from acs_objects o
+ -- where o.object_id = name__object_id)
+ -- connect by object_type = prior supertype
+
+ for obj_type
+ in (select name_method
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = (select object_type
+ from acs_objects o
+ where o.object_id = name__object_id)
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%')
+ order by tree_sortkey desc)
+ loop
+ if obj_type.name_method is not null then
+
+ -- Execute the first name_method we find (since we''re traversing
+ -- up the type hierarchy from the object''s exact type) using
+ -- Native Dynamic SQL, to ascertain the name of this object.
+ --
+ --execute ''select '' || object_type.name_method || ''(:1) from dual''
+ for obj in execute ''select '' || obj_type.name_method || ''('' || name_object_id || '') as object_name'' loop
+ object_name := obj.object_name;
+ exit;
+ end loop;
+
+ exit;
+ end if;
+ end loop;
+
+ return object_name;
+
+end;' language 'plpgsql';
+
+
+-- function default_name
+create function acs_object__default_name (integer)
+returns varchar as '
+declare
+ default_name__object_id alias for $1;
+ object_type_pretty_name acs_object_types.pretty_name%TYPE;
+begin
+ select ot.pretty_name
+ into object_type_pretty_name
+ from acs_objects o, acs_object_types ot
+ where o.object_id = default_name__object_id
+ and o.object_type = ot.object_type;
+
+ return object_type_pretty_name || '' '' || object_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure get_attribute_storage
+create function acs_object__get_attribute_storage (integer,varchar)
+returns text as '
+declare
+ object_id_in alias for $1;
+ attribute_name_in alias for $2;
+-- these three are the out variables
+-- v_column alias for $3;
+-- v_table_name alias for $4;
+-- v_key_sql alias for $5;
+ v_object_type acs_attributes.object_type%TYPE;
+ v_static acs_attributes.static_p%TYPE;
+ v_attr_id acs_attributes.attribute_id%TYPE;
+ v_storage acs_attributes.storage%TYPE;
+ v_attr_name acs_attributes.attribute_name%TYPE;
+ v_id_column varchar(200);
+ v_sql text;
+ v_return text;
+ v_rec record;
+begin
+ -- select
+ -- object_type, id_column
+ -- from
+ -- acs_object_types
+ -- connect by
+ -- object_type = prior supertype
+ -- start with
+ -- object_type = (select object_type from acs_objects
+ -- where object_id = object_id_in)
+
+ -- Determine the attribute parameters
+ select
+ a.attribute_id, a.static_p, a.storage, a.table_name, a.attribute_name,
+ a.object_type, a.column_name, t.id_column
+ into
+ v_attr_id, v_static, v_storage, v_table_name, v_attr_name,
+ v_object_type, v_column, v_id_column
+ from
+ acs_attributes a,
+ (select object_type, id_column
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = (select object_type
+ from acs_objects o
+ where o.object_id = object_id_in)
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%')
+ ) t
+ where
+ a.attribute_name = attribute_name_in
+ and
+ a.object_type = t.object_type;
+
+ if NOT FOUND then
+ raise EXCEPTION ''%: %'', -20000,
+ ''No such attribute '' || v_object_type || ''::'' ||
+ attribute_name_in || '' in acs_object.get_attribute_storage.'';
+ end if;
+
+ -- This should really be done in a trigger on acs_attributes,
+ -- instead of generating it each time in this function
+
+ -- If there is no specific table name for this attribute,
+ -- figure it out based on the object type
+ if v_table_name is null then
+
+ -- Determine the appropriate table name
+ if v_storage = ''generic'' then
+ -- Generic attribute: table name/column are hardcoded
+
+ v_column := ''attr_value'';
+
+ if v_static = ''f'' then
+ v_table_name := ''acs_attribute_values'';
+ v_key_sql := ''(object_id = '' || object_id_in || '' and '' ||
+ ''attribute_id = '' || v_attr_id || '')'';
+ else
+ v_table_name := ''acs_static_attr_values'';
+ v_key_sql := ''(object_type = '''''' || v_object_type || '''''' and '' ||
+ ''attribute_id = '' || v_attr_id || '')'';
+ end if;
+
+ else
+ -- Specific attribute: table name/column need to be retreived
+
+ if v_static = ''f'' then
+ select
+ table_name, id_column
+ into
+ v_table_name, v_id_column
+ from
+ acs_object_types
+ where
+ object_type = v_object_type;
+ if NOT FOUND then
+ raise EXCEPTION ''%: %'', -20000,
+ ''No data found for attribute '' ||
+ v_object_type || ''::'' || attribute_name_in ||
+ '' in acs_object.get_attribute_storage'';
+ end if;
+ else
+ raise EXCEPTION ''%: %'', -20000,
+ ''No table name specified for storage specific static attribute ''
+ || v_object_type || ''::'' || attribute_name_in ||
+ '' in acs_object.get_attribute_storage.'';
+ end if;
+
+ end if;
+ else
+ -- There is a custom table name for this attribute.
+ -- Get the id column out of the acs_object_tables
+ -- Raise an error if not found
+ select id_column into v_id_column from acs_object_type_tables
+ where object_type = v_object_type
+ and table_name = v_table_name;
+ if NOT FOUND then
+ raise EXCEPTION ''%: %'', -20000, ''No data found for attribute ''
+ || v_object_type || ''::'' || attribute_name_in ||
+ '' in acs_object.get_attribute_storage'';
+ end if;
+ end if;
+
+ if v_column is null then
+
+ if v_storage = ''generic'' then
+ v_column := ''attr_value'';
+ else
+ v_column := v_attr_name;
+ end if;
+
+ end if;
+
+ if v_key_sql is null then
+ if v_static = ''f'' then
+ v_key_sql := v_id_column || '' = '' || object_id_in ;
+ else
+ v_key_sql := v_id_column || '' = '''''' || v_object_type || '''''''';
+ end if;
+ end if;
+
+ return v_column || '','' || v_table_name || '','' || v_key_sql;
+
+end;' language 'plpgsql';
+
+
+create function acs_object__get_attr_storage_column(text)
+returns text as '
+declare
+ v_vals alias for $1;
+ v_idx integer;
+begin
+ v_idx := strpos(v_vals,'','');
+ if v_idx = 0 then
+ raise exception ''invalid storage format: acs_object.get_attr_storage_column'';
+ end if;
+
+ return substr(v_vals,1,v_idx - 1);
+
+end;' language 'plpgsql';
+
+create function acs_object__get_attr_storage_table(text)
+returns text as '
+declare
+ v_vals alias for $1;
+ v_idx integer;
+ v_tmp varchar;
+begin
+ v_idx := strpos(v_vals,'','');
+ if v_idx = 0 then
+ raise exception ''invalid storage format: acs_object.get_attr_storage_table'';
+ end if;
+ v_tmp := substr(v_vals,v_idx + 1);
+ v_idx := strpos(v_tmp,'','');
+ if v_idx = 0 then
+ raise exception ''invalid storage format: acs_object.get_attr_storage_table'';
+ end if;
+
+ return substr(v_tmp,1,v_idx - 1);
+
+end;' language 'plpgsql';
+
+create function acs_object__get_attr_storage_sql(text)
+returns text as '
+declare
+ v_vals alias for $1;
+ v_idx integer;
+ v_tmp varchar;
+begin
+ v_idx := strpos(v_vals, '','');
+ if v_idx = 0 then
+ raise exception ''invalid storage format: acs_object.get_attr_storage_sql'';
+ end if;
+ v_tmp := substr(v_vals, v_idx + 1);
+ v_idx := strpos(v_tmp, '','');
+ if v_idx = 0 then
+ raise exception ''invalid storage format: acs_object.get_attr_storage_sql'';
+ end if;
+
+ return substr(v_tmp, v_idx + 1);
+
+end;' language 'plpgsql';
+
+-- function get_attribute
+create function acs_object__get_attribute (integer,varchar)
+returns varchar as '
+declare
+ object_id_in alias for $1;
+ attribute_name_in alias for $2;
+ v_table_name varchar(200);
+ v_column varchar(200);
+ v_key_sql text;
+ v_return text;
+ v_storage text;
+ v_rec record;
+begin
+
+ v_storage := acs_object__get_attribute_storage(object_id_in, attribute_name_in);
+
+ v_column := acs_object__get_attr_storage_column(v_storage);
+ v_table_name := acs_object__get_attr_storage_table(v_storage);
+ v_key_sql := acs_object__get_attr_storage_sql(v_storage);
+
+ for v_rec in execute ''select '' || quote_ident(v_column) || '' as return from '' || quote_ident(v_table_name) || '' where '' || quote_literal(v_key_sql)
+ LOOP
+ if not FOUND then
+ return null;
+ end if;
+ v_return := v_rec.return;
+ exit;
+ end loop;
+
+ return v_return;
+
+end;' language 'plpgsql';
+
+
+-- procedure set_attribute
+create function acs_object__set_attribute (integer,varchar,varchar)
+returns integer as '
+declare
+ object_id_in alias for $1;
+ attribute_name_in alias for $2;
+ value_in alias for $3;
+ v_table_name varchar(200);
+ v_column varchar(200);
+ v_key_sql text;
+ v_return text;
+ v_storage text;
+begin
+
+ v_storage := acs_object__get_attribute_storage(object_id_in, attribute_name_in);
+
+ v_column := acs_object__get_attr_storage_column(v_storage);
+ v_table_name := acs_object__get_attr_storage_table(v_storage);
+ v_key_sql := acs_object__get_attr_storage_sql(v_storage);
+
+ execute ''update '' || quote_identifier(v_table_name) || '' set '' || quote_identifier(v_column) || '' = '' || quote_literal(value_in) || '' where '' || quote_literal(v_key_sql);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function check_context_index
+create function acs_object__check_context_index (integer,integer,integer)
+returns boolean as '
+declare
+ check_context_index__object_id alias for $1;
+ check_context_index__ancestor_id alias for $2;
+ check_context_index__n_generations alias for $3;
+ n_rows integer;
+ n_gens integer;
+begin
+ -- Verify that this row exists in the index.
+ select case when count(*) = 0 then 0 else 1 end into n_rows
+ from acs_object_context_index
+ where object_id = check_context_index__object_id
+ and ancestor_id = check_context_index__ancestor_id;
+
+ if n_rows = 1 then
+ -- Verify that the count is correct.
+ select n_generations into n_gens
+ from acs_object_context_index
+ where object_id = check_context_index__object_id
+ and ancestor_id = check_context_index__ancestor_id;
+
+ if n_gens != n_generations then
+ PERFORM acs_log__error(''acs_object.check_representation'', ''Ancestor '' ||
+ ancestor_id || '' of object '' || object_id ||
+ '' reports being generation '' || n_gens ||
+ '' when it is actually generation '' || n_generations ||
+ ''.'');
+ return ''f'';
+ else
+ return ''t'';
+ end if;
+ else
+ PERFORM acs_log__error(''acs_object.check_representation'', ''Ancestor '' ||
+ ancestor_id || '' of object '' || object_id ||
+ '' is missing an entry in acs_object_context_index.'');
+ return ''f'';
+ end if;
+
+end;' language 'plpgsql';
+
+
+-- function check_object_ancestors
+create function acs_object__check_object_ancestors (integer,integer,integer)
+returns boolean as '
+declare
+ check_object_ancestors__object_id alias for $1;
+ check_object_ancestors__ancestor_id alias for $2;
+ check_object_ancestors__n_generations alias for $3;
+ context_id acs_objects.context_id%TYPE;
+ security_inherit_p acs_objects.security_inherit_p%TYPE;
+ n_rows integer;
+ n_gens integer;
+ result boolean;
+begin
+ -- OBJECT_ID is the object we are verifying
+ -- ANCESTOR_ID is the current ancestor we are tracking
+ -- N_GENERATIONS is how far ancestor_id is from object_id
+
+ -- Note that this function is only supposed to verify that the
+ -- index contains each ancestor for OBJECT_ID. It doesn''''t
+ -- guarantee that there aren''''t extraneous rows or that
+ -- OBJECT_ID''''s children are contained in the index. That is
+ -- verified by seperate functions.
+
+ result := ''t'';
+
+ -- Grab the context and security_inherit_p flag of the current
+ -- ancestor''''s parent.
+ select context_id, security_inherit_p into context_id, security_inherit_p
+ from acs_objects
+ where object_id = check_object_ancestors__ancestor_id;
+
+ if check_object_ancestors__ancestor_id = 0 then
+ if context_id is null then
+ result := ''t'';
+ else
+ -- This can be a constraint, can''''t it?
+ PERFORM acs_log__error(''acs_object.check_representation'',
+ ''Object 0 doesn''''t have a null context_id'');
+ result := ''f'';
+ end if;
+ else
+ if context_id is null or security_inherit_p = ''f'' then
+ context_id := 0;
+ end if;
+
+ if acs_object__check_context_index(check_object_ancestors__object_id, check_object_ancestors__ancestor_id, check_object_ancestors__n_generations) = ''f'' then
+ result := ''f'';
+ end if;
+
+ if acs_object__check_object_ancestors(check_object_ancestors__object_id, context_id,
+ check_object_ancestors__n_generations + 1) = ''f'' then
+ result := ''f'';
+ end if;
+ end if;
+
+ return result;
+
+end;' language 'plpgsql';
+
+
+-- function check_object_descendants
+create function acs_object__check_object_descendants (integer,integer,integer)
+returns boolean as '
+declare
+ object_id alias for $1;
+ descendant_id alias for $2;
+ n_generations alias for $3;
+ result boolean;
+ obj record;
+begin
+ -- OBJECT_ID is the object we are verifying.
+ -- DESCENDANT_ID is the current descendant we are tracking.
+ -- N_GENERATIONS is how far the current DESCENDANT_ID is from
+ -- OBJECT_ID.
+
+ -- This function will verfy that each actualy descendant of
+ -- OBJECT_ID has a row in the index table. It does not check that
+ -- there aren''t extraneous rows or that the ancestors of OBJECT_ID
+ -- are maintained correctly.
+
+ result := ''t'';
+
+ -- First verify that OBJECT_ID and DESCENDANT_ID are actually in
+ -- the index.
+ if acs_object__check_context_index(descendant_id, object_id, n_generations) = ''f'' then
+ result := ''f'';
+ end if;
+
+ -- For every child that reports inheriting from OBJECT_ID we need to call
+ -- ourselves recursively.
+ for obj in (select *
+ from acs_objects
+ where context_id = descendant_id
+ and security_inherit_p = ''t'') loop
+ if acs_object__check_object_descendants(object_id, obj.object_id,
+ n_generations + 1) = ''f'' then
+ result := ''f'';
+ end if;
+ end loop;
+
+ return result;
+
+end;' language 'plpgsql';
+
+
+-- function check_path
+create function acs_object__check_path (integer,integer)
+returns boolean as '
+declare
+ check_path__object_id alias for $1;
+ check_path__ancestor_id alias for $2;
+ context_id acs_objects.context_id%TYPE;
+ security_inherit_p acs_objects.security_inherit_p%TYPE;
+begin
+ if check_path__object_id = check_path__ancestor_id then
+ return ''t'';
+ end if;
+
+ select context_id, security_inherit_p into context_id, security_inherit_p
+ from acs_objects
+ where object_id = check_path__object_id;
+
+ if context_id is null or security_inherit_p = ''f'' then
+ context_id := 0;
+ end if;
+
+ return acs_object__check_path(context_id, check_path__ancestor_id);
+
+end;' language 'plpgsql';
+
+
+-- function check_representation
+create function acs_object__check_representation (integer)
+returns boolean as '
+declare
+ check_representation__object_id alias for $1;
+ result boolean;
+ check_representation__object_type acs_objects.object_type%TYPE;
+ n_rows integer;
+ t record;
+ row record;
+begin
+ result := ''t'';
+ PERFORM acs_log__notice(''acs_object.check_representation'',
+ ''Running acs_object.check_representation on object_id = '' ||
+ check_representation__object_id || ''.'');
+
+ -- If this fails then there isn''''t even an object associated with
+ -- this id. I''m going to let that error propogate as an exception.
+ select object_type into object_type
+ from acs_objects
+ where object_id = check_representation__object_id;
+
+ PERFORM acs_log__notice(''acs_object.check_representation'',
+ ''OBJECT STORAGE INTEGRITY TEST'');
+
+ -- Let''s look through every primary storage table associated with
+ -- this object type and all of its supertypes and make sure there
+ -- is a row with OBJECT_ID as theh primary key.
+ for t in (select t.object_type, t.table_name, t.id_column
+ from acs_object_type_supertype_map m, acs_object_types t
+ where m.ancestor_type = t.object_type
+ and m.object_type = check_representation__object_type
+ union
+ select object_type, table_name, id_column
+ from acs_object_types
+ where object_type = check_representation__object_type)
+ LOOP
+ for row in execute ''select case when count(*) = 0 then 0 else 1 end as n_rows from '' || quote_identifier(t.table_name) || '' where '' || quote_identifier(t.id_column) || '' = '' || check_representation__object_id
+ LOOP
+ n_rows := row.n_rows;
+ exit;
+ end LOOP;
+
+ if n_rows = 0 then
+ result := ''f'';
+ PERFORM acs_log__error(''acs_object.check_representation'',
+ ''Table '' || t.table_name || '' (primary storage for '' ||
+ t.object_type || '') doesn''''t have a row for object '' ||
+ check_representation__object_id || '' of type '' || object_type || ''.'');
+ end if;
+ end loop;
+
+ PERFORM acs_log__notice(''acs_object.check_representation'',
+ ''OBJECT CONTEXT INTEGRITY TEST'');
+
+ -- Do a bunch of dirt simple sanity checks.
+
+ -- First let''s check that all of our ancestors appear in
+ -- acs_object_context_index with the correct generation listed.
+ if acs_object__check_object_ancestors(check_representation__object_id, check_representation__object_id, 0) = ''f'' then
+ result := ''f'';
+ end if;
+
+ -- Now let''s check that all of our descendants appear in
+ -- acs_object_context_index with the correct generation listed.
+ if acs_object__check_object_descendants(check_representation__object_id, check_representation__object_id, 0) = ''f'' then
+ result := ''f'';
+ end if;
+
+ -- Ok, we know that the index contains every entry that it is
+ -- supposed to have. Now let''s make sure it doesn''t contain any
+ -- extraneous entries.
+ for row in (select *
+ from acs_object_context_index
+ where object_id = check_representation__object_id
+ or ancestor_id = check_representation__object_id) loop
+ if acs_object__check_path(row.object_id, row.ancestor_id) = ''f'' then
+ PERFORM acs_log__error(''acs_object.check_representation'',
+ ''acs_object_context_index contains an extraneous row: '' ||
+ ''object_id = '' || row.object_id || '', ancestor_id = '' ||
+ row.ancestor_id || '', n_generations = '' ||
+ row.n_generations || ''.'');
+ result := ''f'';
+ end if;
+ end loop;
+
+ PERFORM acs_log__notice(''acs_object.check_representation'',
+ ''Done running acs_object.check_representation '' ||
+ ''on object_id = '' || check_representation__object_id || ''.'');
+
+ return result;
+
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
+-------------------
+-- MISCELLANEOUS --
+-------------------
+
+create table general_objects (
+ object_id integer not null
+ constraint general_objects_object_id_fk
+ references acs_objects (object_id)
+ constraint general_objects_pk
+ primary key,
+ on_which_table varchar(30) not null,
+ on_what_id integer not null,
+ constraint general_objects_un
+ unique (on_which_table, on_what_id)
+);
+
+comment on table general_objects is '
+ This table can be used to treat non-acs_objects as acs_objects for
+ purposes of access control, categorization, etc.
+';
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,29 @@
+--
+-- acs-kernel/sql/acs-objects-drop.sql
+--
+-- DDL commands to purge the ACS Objects data model
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @creation-date 2000-05-18
+-- @cvs-id acs-objects-drop.sql,v 1.5 2000/10/24 22:26:18 bquinn Exp
+--
+
+\t
+drop table general_objects;
+select drop_package('acs_object');
+drop table acs_static_attr_values;
+drop table acs_attribute_values;
+drop view acs_attribute_value_id_seq;
+drop sequence t_acs_attribute_value_id_seq;
+drop trigger acs_objects_context_id_del_tr;
+drop trigger acs_objects_context_id_up_tr;
+drop trigger acs_objects_context_id_in_tr;
+drop view acs_object_contexts;
+drop view acs_object_paths;
+drop table acs_object_context_index;
+drop trigger acs_objects_last_mod_update_tr;
+drop trigger acs_objects_mod_ip_insert_tr;
+drop table acs_objects;
+drop view acs_objbect_id_seq;
+drop sequence t_acs_object_id_seq;
+\t
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,426 @@
+--
+-- acs-kernel/sql/acs-permissions-create.sql
+--
+-- The ACS core permissioning system. The knowledge level of system
+-- allows you to define a hierarchichal system of privilages, and
+-- associate them with low level operations on object types. The
+-- operational level allows you to grant to any party a privilege on
+-- any object.
+--
+-- @author Rafael Schloming (rhs@mit.edu)
+--
+-- @creation-date 2000-08-13
+--
+-- @cvs-id acs-permissions-create.sql,v 1.10.2.2 2001/01/12 22:59:20 oumi Exp
+--
+
+
+---------------------------------------------
+-- KNOWLEDGE LEVEL: PRIVILEGES AND ACTIONS --
+---------------------------------------------
+
+-- suggestion: acs_methods, acs_operations, acs_transactions?
+-- what about cross-type actions? new-stuff? site-wide search?
+
+--create table acs_methods (
+-- object_type not null constraint acs_methods_object_type_fk
+-- references acs_object_types (object_type),
+-- method varchar2(100) not null,
+-- constraint acs_methods_pk
+-- primary key (object_type, method)
+--);
+
+--comment on table acs_methods is '
+-- Each row in the acs_methods table directly corresponds to a
+-- transaction on an object. For example an sql statement that updates a
+-- bboard message would require an entry in this table.
+--'
+
+create table acs_privileges (
+ privilege varchar(100) not null constraint acs_privileges_pk
+ primary key,
+ pretty_name varchar(100) default '' not null,
+ pretty_plural varchar(100) default '' not null
+);
+
+create table acs_privilege_hierarchy (
+ privilege varchar(100) not null constraint acs_priv_hier_priv_fk
+ references acs_privileges (privilege),
+ child_privilege varchar(100) not null constraint acs_priv_hier_child_priv_fk
+ references acs_privileges (privilege),
+ constraint acs_privilege_hierarchy_pk
+ primary key (privilege, child_privilege)
+);
+
+create index acs_priv_hier_child_priv_idx on acs_privilege_hierarchy (child_privilege);
+
+--create table acs_privilege_method_rules (
+-- privilege not null constraint acs_priv_method_rules_priv_fk
+-- references acs_privileges (privilege),
+-- object_type varchar2(100) not null,
+-- method varchar2(100) not null,
+-- constraint acs_privilege_method_rules_pk
+-- primary key (privilege, object_type, method),
+-- constraint acs_priv_meth_rul_type_meth_fk
+-- foreign key (object_type, method) references acs_methods
+--);
+
+comment on table acs_privileges is '
+ The rows in this table correspond to aggregations of specific
+ methods. Privileges share a global namespace. This is to avoid a
+ situation where granting the foo privilege on one type of object can
+ have an entirely different meaning than granting the foo privilege on
+ another type of object.
+';
+
+comment on table acs_privilege_hierarchy is '
+ The acs_privilege_hierarchy gives us an easy way to say: The foo
+ privilege is a superset of the bar privilege.
+';
+
+--comment on table acs_privilege_method_rules is '
+-- The privilege method map allows us to create rules that specify which
+-- methods a certain privilege is allowed to invoke in the context of a
+-- particular object_type. Note that the same privilege can have
+-- different methods for different object_types. This is because each
+-- method corresponds to a piece of code, and the code that displays an
+-- instance of foo will be different than the code that displays an
+-- instance of bar. If there are no methods defined for a particular
+-- (privilege, object_type) pair, then that privilege is not relavent to
+-- that object type, for example there is no way to moderate a user, so
+-- there would be no additional methods that you could invoke if you
+-- were granted moderate on a user.
+--'
+
+--create or replace view acs_privilege_method_map
+--as select r1.privilege, pmr.object_type, pmr.method
+-- from acs_privileges r1, acs_privileges r2, acs_privilege_method_rules pmr
+-- where r2.privilege in (select distinct rh.child_privilege
+-- from acs_privilege_hierarchy rh
+-- start with privilege = r1.privilege
+-- connect by prior child_privilege = privilege
+-- union
+-- select r1.privilege
+-- from dual)
+-- and r2.privilege = pmr.privilege;
+
+-- create or replace package acs_privilege
+-- as
+--
+-- procedure create_privilege (
+-- privilege in acs_privileges.privilege%TYPE,
+-- pretty_name in acs_privileges.pretty_name%TYPE default null,
+-- pretty_plural in acs_privileges.pretty_plural%TYPE default null
+-- );
+--
+-- procedure drop_privilege (
+-- privilege in acs_privileges.privilege%TYPE
+-- );
+--
+-- procedure add_child (
+-- privilege in acs_privileges.privilege%TYPE,
+-- child_privilege in acs_privileges.privilege%TYPE
+-- );
+--
+-- procedure remove_child (
+-- privilege in acs_privileges.privilege%TYPE,
+-- child_privilege in acs_privileges.privilege%TYPE
+-- );
+--
+-- end;
+
+-- show errors
+
+-- create or replace package body acs_privilege
+-- procedure create_privilege
+create function acs_privilege__create_privilege (varchar,varchar,varchar)
+returns integer as '
+declare
+ create_privilege__privilege alias for $1;
+ create_privilege__pretty_name alias for $2;
+ create_privilege__pretty_plural alias for $3;
+begin
+ insert into acs_privileges
+ (privilege, pretty_name, pretty_plural)
+ values
+ (create_privilege__privilege,
+ coalesce(create_privilege__pretty_name,''''),
+ coalesce(create_privilege__pretty_plural,''''));
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure drop_privilege
+create function acs_privilege__drop_privilege (varchar)
+returns integer as '
+declare
+ drop_privilege__privilege alias for $1;
+begin
+ delete from acs_privileges
+ where privilege = drop_privilege__privilege;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure add_child
+create function acs_privilege__add_child (varchar,varchar)
+returns integer as '
+declare
+ add_child__privilege alias for $1;
+ add_child__child_privilege alias for $2;
+begin
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ (add_child__privilege, add_child__child_privilege);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure remove_child
+create function acs_privilege__remove_child (varchar,varchar)
+returns integer as '
+declare
+ remove_child__privilege alias for $1;
+ remove_child__child_privilege alias for $2;
+begin
+ delete from acs_privilege_hierarchy
+ where privilege = remove_child__privilege
+ and child_privilege = remove_child__child_privilege;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
+
+------------------------------------
+-- OPERATIONAL LEVEL: PERMISSIONS --
+------------------------------------
+
+create table acs_permissions (
+ object_id integer not null
+ constraint acs_permissions_on_what_id_fk
+ references acs_objects (object_id),
+ grantee_id integer not null
+ constraint acs_permissions_grantee_id_fk
+ references parties (party_id),
+ privilege varchar(100) not null constraint acs_permissions_priv_fk
+ references acs_privileges (privilege),
+ constraint acs_permissions_pk
+ primary key (object_id, grantee_id, privilege)
+);
+
+create index acs_permissions_grantee_idx on acs_permissions (grantee_id);
+create index acs_permissions_privilege_idx on acs_permissions (privilege);
+
+create view acs_privilege_descendant_map
+as select p1.privilege, p2.privilege as descendant
+ from acs_privileges p1, acs_privileges p2
+ where p2.privilege in (select child_privilege
+ from acs_privilege_hierarchy
+ start with privilege = p1.privilege
+ connect by prior child_privilege = privilege)
+ or p2.privilege = p1.privilege;
+
+create view acs_permissions_all
+as select op.object_id, p.grantee_id, p.privilege
+ from acs_object_paths op, acs_permissions p
+ where op.ancestor_id = p.object_id;
+
+create view acs_object_grantee_priv_map
+as select a.object_id, a.grantee_id, m.descendant as privilege
+ from acs_permissions_all a, acs_privilege_descendant_map m
+ where a.privilege = m.privilege;
+
+-- The last two unions make sure that the_public gets expaned to all
+-- users plus 0 (the default user_id) we should probably figure out a
+-- better way to handle this eventually since this view is getting
+-- pretty freaking hairy. I'd love to be able to move this stuff into
+-- a Java middle tier.
+
+create view acs_object_party_privilege_map
+as select ogpm.object_id, gmm.member_id as party_id, ogpm.privilege
+ from acs_object_grantee_priv_map ogpm, group_approved_member_map gmm
+ where ogpm.grantee_id = gmm.group_id
+ union
+ select ogpm.object_id, rsmm.member_id as party_id, ogpm.privilege
+ from acs_object_grantee_priv_map ogpm, rel_seg_approved_member_map rsmm
+ where ogpm.grantee_id = rsmm.segment_id
+ union
+ select object_id, grantee_id as party_id, privilege
+ from acs_object_grantee_priv_map
+ union
+ select object_id, u.user_id as party_id, privilege
+ from acs_object_grantee_priv_map m, users u
+ where m.grantee_id = -1
+ union
+ select object_id, 0 as party_id, privilege
+ from acs_object_grantee_priv_map
+ where grantee_id = -1;
+
+----------------------------------------------------
+-- ALTERNATE VIEW: ALL_OBJECT_PARTY_PRIVILEGE_MAP --
+----------------------------------------------------
+
+-- This view is a helper for all_object_party_privilege_map
+create view acs_grantee_party_map as
+ select -1 as grantee_id, 0 as party_id from dual
+ union all
+ select -1 as grantee_id, user_id as party_id
+ from users
+ union all
+ select party_id as grantee_id, party_id
+ from parties
+ union all
+ select segment_id as grantee_id, member_id
+ from rel_seg_approved_member_map
+ union all
+ select group_id as grantee_id, member_id as party_id
+ from group_approved_member_map;
+
+-- This view is like acs_object_party_privilege_map, but does not
+-- necessarily return distinct rows. It may be *much* faster to join
+-- against this view instead of acs_object_party_privilege_map, and is
+-- usually not much slower. The tradeoff for the performance boost is
+-- increased complexity in your usage of the view. Example usage that I've
+-- found works well is:
+--
+-- select DISTINCT
+-- my_table.*
+-- from my_table,
+-- (select object_id
+-- from all_object_party_privilege_map
+-- where party_id = :user_id and privilege = :privilege) oppm
+-- where oppm.object_id = my_table.my_id;
+--
+/*
+create view all_object_party_privilege_map as
+select /*+ ORDERED */
+ op.object_id,
+ pdm.descendant as privilege,
+ gpm.party_id as party_id
+ from acs_object_paths op,
+ acs_permissions p,
+ acs_privilege_descendant_map pdm,
+ acs_grantee_party_map gpm
+ where op.ancestor_id = p.object_id
+ and pdm.privilege = p.privilege
+ and gpm.grantee_id = p.grantee_id;
+*/
+
+create view all_object_party_privilege_map as
+select op.object_id,
+ pdm.descendant as privilege,
+ gpm.party_id as party_id
+ from acs_object_paths op,
+ acs_permissions p,
+ acs_privilege_descendant_map pdm,
+ acs_grantee_party_map gpm
+ where op.ancestor_id = p.object_id
+ and pdm.privilege = p.privilege
+ and gpm.grantee_id = p.grantee_id;
+
+
+--create or replace view acs_object_party_method_map
+--as select opp.object_id, opp.party_id, pm.object_type, pm.method
+-- from acs_object_party_privilege_map opp, acs_privilege_method_map pm
+-- where opp.privilege = pm.privilege;
+
+-- create or replace package acs_permission
+-- as
+--
+-- procedure grant_permission (
+-- object_id acs_permissions.object_id%TYPE,
+-- grantee_id acs_permissions.grantee_id%TYPE,
+-- privilege acs_permissions.privilege%TYPE
+-- );
+--
+-- procedure revoke_permission (
+-- object_id acs_permissions.object_id%TYPE,
+-- grantee_id acs_permissions.grantee_id%TYPE,
+-- privilege acs_permissions.privilege%TYPE
+-- );
+--
+-- function permission_p (
+-- object_id acs_objects.object_id%TYPE,
+-- party_id parties.party_id%TYPE,
+-- privilege acs_privileges.privilege%TYPE
+-- ) return char;
+--
+-- end acs_permission;
+
+-- show errors
+
+-- create or replace package body acs_permission
+-- procedure grant_permission
+create function acs_permission__grant_permission (integer, integer, varchar)
+returns integer as '
+declare
+ grant_permission__object_id alias for $1;
+ grant_permission__grantee_id alias for $2;
+ grant_permission__privilege alias for $3;
+begin
+ insert into acs_permissions
+ (object_id, grantee_id, privilege)
+ values
+ (grant_permission__object_id, grant_permission__grantee_id, grant_permission__privilege);
+
+ -- FIXME: find out what this means?
+ -- exception
+ -- when dup_val_on_index then
+ -- return;
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure revoke_permission
+create function acs_permission__revoke_permission (integer, integer, varchar)
+returns integer as '
+declare
+ revoke_permission__object_id alias for $1;
+ revoke_permission__grantee_id alias for $2;
+ revoke_permission__privilege alias for $3;
+begin
+ delete from acs_permissions
+ where object_id = revoke_permission__object_id
+ and grantee_id = revoke_permission__grantee_id
+ and privilege = revoke_permission__privilege;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function permission_p
+create function acs_permission__permission_p ()
+returns boolean as '
+declare
+ permission_p__object_id integer;
+ permission_p__party_id integer;
+ permission_p__privilege integer;
+ exists_p boolean;
+begin
+ -- We should question whether we really want to use the
+ -- acs_object_party_privilege_map since it unions the
+ -- difference queries. UNION ALL would be more efficient.
+ -- Also, we may want to test replacing the decode with
+ -- select count(*) from dual where exists ...
+ -- 1/12/2001, mbryzek
+ select case when count(*) = 0 then ''f'' else ''t'' end into exists_p
+ from acs_object_party_privilege_map
+ where object_id = permission_p__object_id
+ and party_id = permission_p__party_id
+ and privilege = permission_p__privilege;
+
+ return exists_p;
+
+end;' language 'plpgsql';
+
+
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,25 @@
+--
+-- packages/acs-kernel/sql/acs-permissions-drop.sql
+--
+-- @creation-date 2000-08-13
+--
+-- @author rhs@mit.edu
+--
+-- @cvs-id acs-permissions-drop.sql,v 1.5 2000/10/24 22:26:19 bquinn Exp
+--
+
+--drop view acs_object_party_method_map;
+drop view acs_object_party_privilege_map;
+drop view acs_object_grantee_priv_map;
+drop view acs_permissions_all;
+drop view acs_privilege_descendant_map;
+\t
+select drop_package('acs_permission');
+drop table acs_permissions;
+--drop view acs_privilege_method_map;
+--drop table acs_privilege_method_rules;
+select drop_package('acs_privilege');
+\t
+drop table acs_privilege_hierarchy;
+drop table acs_privileges;
+--drop table acs_methods;
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-relationships-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-relationships-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-relationships-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,603 @@
+--
+-- packages/acs-kernel/sql/acs-relationships-create.sql
+--
+-- XXX Fill this in later.
+--
+-- @creation-date 2000-08-13
+--
+-- @author rhs@mit.edu
+--
+-- @cvs-id acs-relationships-create.sql,v 1.7.2.2 2001/01/12 23:03:26 mbryzek Exp
+--
+
+----------------------------------------------------------------
+-- KNOWLEDGE LEVEL: RELATIONSHIP TYPES AND RELATIONSHIP RULES --
+----------------------------------------------------------------
+
+create table acs_rel_roles (
+ role varchar(100) not null
+ constraint acs_rel_roles_pk primary key,
+ pretty_name varchar(100) not null,
+ pretty_plural varchar(100) not null
+);
+
+create table acs_rel_types (
+ rel_type varchar(100) not null
+ constraint acs_rel_types_pk primary key
+ constraint acs_rel_types_rel_type_fk
+ references acs_object_types(object_type),
+ object_type_one varchar(100) not null
+ constraint acs_rel_types_obj_type_1_fk
+ references acs_object_types (object_type),
+ role_one varchar(100) constraint acs_rel_types_role_1_fk
+ references acs_rel_roles (role),
+ min_n_rels_one integer default 0 not null
+ constraint acs_rel_types_min_n_1_ck
+ check (min_n_rels_one >= 0),
+ max_n_rels_one integer
+ constraint acs_rel_types_max_n_1_ck
+ check (max_n_rels_one >= 0),
+ object_type_two varchar(100) not null
+ constraint acs_rel_types_obj_type_2_fk
+ references acs_object_types (object_type),
+ role_two varchar(100) constraint acs_rel_types_role_2_fk
+ references acs_rel_roles (role),
+ min_n_rels_two integer default 0 not null
+ constraint acs_rel_types_min_n_2_ck
+ check (min_n_rels_two >= 0),
+ max_n_rels_two integer
+ constraint acs_rel_types_max_n_2_ck
+ check (max_n_rels_two >= 0),
+ constraint acs_rel_types_n_rels_one_ck
+ check (min_n_rels_one <= max_n_rels_one),
+ constraint acs_rel_types_n_rels_two_ck
+ check (min_n_rels_two <= max_n_rels_two)
+);
+
+create index acs_rel_types_objtypeone_idx on acs_rel_types (object_type_one);
+create index acs_rel_types_role_one_idx on acs_rel_types (role_one);
+create index acs_rel_types_objtypetwo_idx on acs_rel_types (object_type_two);
+create index acs_rel_types_role_two_idx on acs_rel_types (role_two);
+
+comment on table acs_rel_types is '
+ Each row in acs_rel_types
represents a type of
+ relationship between objects. For example, the following DML
+ statement:
+
+ defines an "employment" relationship type that can be expressed in + in natural language as: ++ insert into acs_rel_types + (rel_type, + object_type_one, role_one, min_n_rels_one, max_n_rels_one, + object_type_two, role_two, min_n_rels_two, max_n_rels_two) + values + (''employment'', + ''person'', ''employee'', 0, null, + ''company'', ''employer'', 0, null) +
+ A person may be the employee of zero or more companies, and a company + may be the employer of zero or more people. ++'; + +-- create or replace package acs_rel_type +-- as +-- +-- procedure create_role ( +-- role in acs_rel_roles.role%TYPE, +-- pretty_name in acs_rel_roles.pretty_name%TYPE default null, +-- pretty_plural in acs_rel_roles.pretty_plural%TYPE default null +-- ); +-- +-- procedure drop_role ( +-- role in acs_rel_roles.role%TYPE +-- ); +-- +-- function role_pretty_name ( +-- role in acs_rel_roles.role%TYPE +-- ) return acs_rel_roles.pretty_name%TYPE; +-- +-- function role_pretty_plural ( +-- role in acs_rel_roles.role%TYPE +-- ) return acs_rel_roles.pretty_plural%TYPE; +-- +-- procedure create_type ( +-- rel_type in acs_rel_types.rel_type%TYPE, +-- pretty_name in acs_object_types.pretty_name%TYPE, +-- pretty_plural in acs_object_types.pretty_plural%TYPE, +-- supertype in acs_object_types.supertype%TYPE +-- default 'relationship', +-- table_name in acs_object_types.table_name%TYPE, +-- id_column in acs_object_types.id_column%TYPE, +-- package_name in acs_object_types.package_name%TYPE, +-- abstract_p in acs_object_types.abstract_p%TYPE default 'f', +-- type_extension_table in acs_object_types.type_extension_table%TYPE +-- default null, +-- name_method in acs_object_types.name_method%TYPE default null, +-- object_type_one in acs_rel_types.object_type_one%TYPE, +-- role_one in acs_rel_types.role_one%TYPE default null, +-- min_n_rels_one in acs_rel_types.min_n_rels_one%TYPE, +-- max_n_rels_one in acs_rel_types.max_n_rels_one%TYPE, +-- object_type_two in acs_rel_types.object_type_two%TYPE, +-- role_two in acs_rel_types.role_two%TYPE default null, +-- min_n_rels_two in acs_rel_types.min_n_rels_two%TYPE, +-- max_n_rels_two in acs_rel_types.max_n_rels_two%TYPE +-- ); +-- +-- procedure drop_type ( +-- rel_type in acs_rel_types.rel_type%TYPE, +-- cascade_p in char default 'f' +-- ); +-- +-- end acs_rel_type; + +-- show errors + +-- create or replace package body acs_rel_type +-- procedure create_role +create function acs_rel_type__create_role (varchar,varchar,varchar) +returns integer as ' +declare + create_role__role alias for $1; + create_role__pretty_name alias for $2; + create_role__pretty_plural alias for $3; +begin + insert into acs_rel_roles + (role, pretty_name, pretty_plural) + values + (create_role__role, coalesce(create_role__pretty_name,create_role__role), coalesce(create_role__pretty_plural,create_role__role)); + + return 0; +end;' language 'plpgsql'; + + +-- procedure drop_role +create function acs_rel_type__drop_role (varchar) +returns integer as ' +declare + drop_role__role alias for $1; +begin + delete from acs_rel_roles + where role = drop_role__role; + + return 0; +end;' language 'plpgsql'; + + +-- function role_pretty_name +create function acs_rel_type__role_pretty_name (varchar) +returns varchar as ' +declare + role_pretty_name__role alias for $1; + v_pretty_name acs_rel_roles.pretty_name%TYPE; +begin + select r.pretty_name into v_pretty_name + from acs_rel_roles r + where r.role = role_pretty_name__role; + + return v_pretty_name; + +end;' language 'plpgsql'; + + +-- function role_pretty_plural +create function acs_rel_type__role_pretty_plural (varchar) +returns varchar as ' +declare + role_pretty_plural__role alias for $1; + v_pretty_plural acs_rel_roles.pretty_plural%TYPE; +begin + select r.pretty_plural into v_pretty_plural + from acs_rel_roles r + where r.role = role_pretty_plural__role; + + return v_pretty_plural; + +end;' language 'plpgsql'; + + +-- procedure create_type +create function acs_rel_type__create_type (varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,varchar,varchar,integer,integer) +returns integer as ' +declare + create_type__rel_type alias for $1; + create_type__pretty_name alias for $2; + create_type__pretty_plural alias for $3; + create_type__table_name alias for $4; + create_type__id_column alias for $5; + create_type__package_name alias for $6; + create_type__object_type_one alias for $7; + create_type__role_one alias for $8; + + create_type__min_n_rels_one alias for $9; + create_type__max_n_rels_one alias for $10; + + create_type__object_type_two alias for $11; + create_type__role_two alias for $12; + + create_type__min_n_rels_two alias for $13; + create_type__max_n_rels_two alias for $14; + + type_extension_table acs_object_types.type_extension_table%TYPE default null; + supertype acs_object_types.supertype%TYPE default ''relationship''; + abstract_p acs_object_types.abstract_p%TYPE default ''f''; + name_method acs_object_types.name_method%TYPE default null; +begin + PERFORM acs_object_type__create_type( + create_type__rel_type, + create_type__pretty_name, + create_type__pretty_plural, + supertype, + create_type__table_name, + create_type__id_column, + create_type__package_name, + abstract_p, + type_extension_table, + name_method + ); + + insert into acs_rel_types + (rel_type, + object_type_one, role_one, + min_n_rels_one, max_n_rels_one, + object_type_two, role_two, + min_n_rels_two, max_n_rels_two) + values + (create_type__rel_type, + create_type__object_type_one, create_type__role_one, + create_type__min_n_rels_one, create_type__max_n_rels_one, + create_type__object_type_two, create_type__role_two, + create_type__min_n_rels_two, create_type__max_n_rels_two); + + return 0; +end;' language 'plpgsql'; + + + +-- procedure create_type +create function acs_rel_type__create_type (varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,varchar,integer,integer) +returns integer as ' +declare + create_type__rel_type alias for $1; + create_type__pretty_name alias for $2; + create_type__pretty_plural alias for $3; + create_type__supertype alias for $4; + create_type__table_name alias for $5; + create_type__id_column alias for $6; + create_type__package_name alias for $7; + create_type__type_extension_table alias for $8; + create_type__object_type_one alias for $9; + create_type__min_n_rels_one alias for $10; + create_type__max_n_rels_one alias for $11; + create_type__object_type_two alias for $12; + create_type__min_n_rels_two alias for $13; + create_type__max_n_rels_two alias for $14; + + abstract_p acs_object_types.abstract_p%TYPE default ''f''; + name_method acs_object_types.name_method%TYPE default null; + create_type__role_one acs_rel_types.role_one%TYPE default null; + create_type__role_two acs_rel_types.role_two%TYPE default null; +begin + + PERFORM acs_object_type__create_type( + create_type__rel_type, + create_type__pretty_name, + create_type__pretty_plural, + create_type__supertype, + create_type__table_name, + create_type__id_column, + create_type__package_name, + abstract_p, + create_type__type_extension_table, + name_method + ); + + insert into acs_rel_types + (rel_type, + object_type_one, role_one, + min_n_rels_one, max_n_rels_one, + object_type_two, role_two, + min_n_rels_two, max_n_rels_two) + values + (create_type__rel_type, + create_type__object_type_one, create_type__role_one, + create_type__min_n_rels_one, create_type__max_n_rels_one, + create_type__object_type_two, create_type__role_two, + create_type__min_n_rels_two, create_type__max_n_rels_two); + + return 0; +end;' language 'plpgsql'; + + +-- procedure drop_type +create function acs_rel_type__drop_type (varchar,boolean) +returns integer as ' +declare + drop_type__rel_type alias for $1; + drop_type__cascade_p alias for $2; +begin + -- XXX do cascade_p + delete from acs_rel_types + where rel_type = drop_type__rel_type; + + PERFORM acs_object_type__drop_type(drop_type__rel_type, drop_type__cascade_p); + + return 0; +end;' language 'plpgsql'; + + + +-- show errors + select acs_rel_type__create_type ( + 'relationship', + 'Relationship', + 'Relationships', + 'acs_object', + 'acs_rels', + 'rel_id', + 'acs_rel', + 'acs_rel_types', + 'acs_object', + 0, + null::integer, + 'acs_object', + 0, + null::integer + ); + + +-- show errors + +-------------------------------------- +-- OPERATIONAL LEVEL: RELATIONSHIPS -- +-------------------------------------- + +create sequence t_acs_rel_id_seq; +create view acs_rel_id_seq as +select nextval('t_acs_rel_id_seq') as nextval; + +create table acs_rels ( + rel_id integer not null + constraint acs_rels_rel_id_fk + references acs_objects (object_id) + constraint acs_rels_pk primary key, + rel_type varchar(100) not null + constraint acs_rels_rel_type_fk + references acs_rel_types (rel_type), + object_id_one integer not null + constraint acs_object_rels_one_fk + references acs_objects (object_id), + object_id_two integer not null + constraint acs_object_rels_two_fk + references acs_objects (object_id), + constraint acs_object_rels_un unique + (rel_type, object_id_one, object_id_two) +); + +create index acs_rels_object_id_one_idx on acs_rels (object_id_one); +create index acs_rels_object_id_two_idx on acs_rels (object_id_two); + +comment on table acs_rels is ' + The acs_rels table is essentially a generic mapping table for + acs_objects. Once we come up with a way to associate attributes with + relationship types, we could replace many of the ACS 3.x mapping + tables like user_content_map, user_group_map, and + user_group_type_modules_map with this one table. Much application + logic consists of asking questions like "Does object X have a + relationship of type Y to object Z?" where all that differs is + X, Y, and Z. Thus, the value of consolidating many mapping tables + into one is that we can provide a generic API for defining and + querying relationships. In addition, we may need to design a way to + enable "type_specific" storage for relationships (i.e., foreign key + columns for one-to-many relationships and custom mapping tables for + many-to-many relationships), instead of only supporting "generic" + storage in the acs_rels table. This would parallel what we do with + acs_attributes. +'; + +-------------- +-- TRIGGERS -- +-------------- + +-- added by oumi@arsdigita.com - Jan 11, 2001 + +create function acs_rels_in_tr () returns opaque as ' +declare + dummy integer; + target_object_type_one acs_object_types.object_type%TYPE; + target_object_type_two acs_object_types.object_type%TYPE; + actual_object_type_one acs_object_types.object_type%TYPE; + actual_object_type_two acs_object_types.object_type%TYPE; +begin + + -- validate that the relation being added is between objects of the + -- correct object_type. If no rows are returned by this query, + -- then the types are wrong and we should return an error. + -- select 1 into dummy + -- from acs_rel_types rt, + -- acs_objects o1, + -- acs_objects o2 + -- where exists (select 1 + -- from acs_object_types t + -- where t.object_type = o1.object_type + -- connect by prior t.object_type = t.supertype + -- start with t.object_type = rt.object_type_one) + -- and exists (select 1 + -- from acs_object_types t + -- where t.object_type = o2.object_type + -- connect by prior t.object_type = t.supertype + -- start with t.object_type = rt.object_type_two) + -- and rt.rel_type = new.rel_type + -- and o1.object_id = new.object_id_one + -- and o2.object_id = new.object_id_two; + + select 1 into dummy + from acs_rel_types rt, + acs_objects o1, + acs_objects o2 + where exists (select 1 + from acs_object_types t + where t.object_type = o1.object_type + and t.tree_sortkey + like (select o.tree_sortkey || '%' + from acs_object_types o + where o.object_type = rt.object_type_one)) + and exists (select 1 + from acs_object_types t + where t.object_type = o2.object_type + and t.tree_sortkey + like (select o.tree_sortkey || '%' + from acs_object_types o + where o.object_type = rt.object_type_two)) + and rt.rel_type = new.rel_type + and o1.object_id = new.object_id_one + and o2.object_id = new.object_id_two; + + if NOT FOUND then + + -- At least one of the object types must have been wrong. + -- Get all the object type information and print it out. + select rt.object_type_one, rt.object_type_two, + o1.object_type, o2.object_type + into target_object_type_one, target_object_type_two, + actual_object_type_one, actual_object_type_two + from acs_rel_types rt, acs_objects o1, acs_objects o2 + where rt.rel_type = new.rel_type + and o1.object_id = new.object_id_one + and o2.object_id = new.object_id_two; + + raise EXCEPTION ''%: %'', -20001, + new.rel_type || '' violation: Invalid object types. '' || + ''Object '' || new.object_id_one || + '' ('' || actual_object_type_one || '') '' || + ''must be of type '' || target_object_type_one || ''. '' || + ''Object '' || new.object_id_two || + '' ('' || actual_object_type_two || '') '' || + ''must be of type '' || target_object_type_two || ''.''; + end if; + + return new; + +end;' language 'plpgsql'; + +create trigger acs_rels_in_tr before insert or update on acs_rels +for each row execute procedure acs_rels_in_tr (); + +-- show errors + + +-- create or replace package acs_rel +-- as +-- +-- function new ( +-- rel_id in acs_rels.rel_id%TYPE default null, +-- rel_type in acs_rels.rel_type%TYPE default 'relationship', +-- object_id_one in acs_rels.object_id_one%TYPE, +-- object_id_two in acs_rels.object_id_two%TYPE, +-- context_id in acs_objects.context_id%TYPE default null, +-- creation_user in acs_objects.creation_user%TYPE default null, +-- x creation_ip in acs_objects.creation_ip%TYPE default null +-- ) return acs_rels.rel_id%TYPE; +-- +-- procedure delete ( +-- rel_id in acs_rels.rel_id%TYPE +-- ); +-- +-- end; + +-- show errors + +-- create or replace package body acs_rel +-- function new +create function acs_rel__new (integer,varchar,integer,integer,integer,integer,varchar) +returns integer as ' +declare + new__rel_id alias for $1; + new__rel_type alias for $2; + new__object_id_one alias for $3; + new__object_id_two alias for $4; + context_id alias for $5; + creation_user alias for $6; + creation_ip alias for $7; + v_rel_id acs_rels.rel_id%TYPE; +begin + -- XXX This should check that object_id_one and object_id_two are + -- of the appropriate types. + v_rel_id := acs_object__new ( + new__rel_id, + new__rel_type, + now(), + creation_user, + creation_ip, + context_id + ); + + insert into acs_rels + (rel_id, rel_type, object_id_one, object_id_two) + values + (v_rel_id, new__rel_type, new__object_id_one, new__object_id_two); + + return v_rel_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function acs_rel__delete (integer) +returns integer as ' +declare + rel_id alias for $1; +begin + PERFORM acs_object__delete(rel_id); + + return 0; +end;' language 'plpgsql'; + +----------- +-- VIEWS -- +----------- + +-- These views are handy for metadata driven UI + +-- View: rel_types_valid_obj_one_types +-- +-- Question: Given rel_type :rel_type, +-- +-- What are all the valid object_types for object_id_one of +-- a relation of type :rel_type +-- +-- Answer: select object_type +-- from rel_types_valid_obj__one_types +-- where rel_type = :rel_type +-- +create view rel_types_valid_obj_one_types as +select rt.rel_type, th.object_type +from acs_rel_types rt, + (select object_type, ancestor_type + from acs_object_type_supertype_map + UNION ALL + select object_type, object_type as ancestor_type + from acs_object_types) th +where rt.object_type_one = th.ancestor_type; + +-- View: rel_types_valid_obj_two_types +-- +-- Question: Given rel_type :rel_type, +-- +-- What are all the valid object_types for object_id_two of +-- a relation of type :rel_type +-- +-- Answer: select object_type +-- from rel_types_valid_obj_two_types +-- where rel_type = :rel_type +-- +create view rel_types_valid_obj_two_types as +select rt.rel_type, th.object_type +from acs_rel_types rt, + (select object_type, ancestor_type + from acs_object_type_supertype_map + UNION ALL + select object_type, object_type as ancestor_type + from acs_object_types) th +where rt.object_type_two = th.ancestor_type; Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-relationships-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-relationships-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/acs-relationships-drop.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,19 @@ +-- +-- packages/acs-kernel/sql/acs-relationships-drop.sql +-- +-- @creation-date 2000-08-13 +-- +-- @author rhs@mit.edu +-- +-- @cvs-id acs-relationships-drop.sql,v 1.5 2000/10/24 22:26:19 bquinn Exp +-- + +\t +select drop_package('acs_rel'); +select drop_package('acs_rel_type'); +\t +drop table acs_rels; +drop view acs_rel_id_seq; +drop sequence t_acs_rel_id_seq; +drop table acs_rel_types; +drop table acs_rel_roles; Index: openacs-4/packages/acs-kernel/sql/postgresql/apm-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/apm-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/apm-create.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,3023 @@ +-- +-- /packages/acs-kernel/sql/apm-create.sql +-- +-- Data model for the ACS Package Manager (APM) +-- +-- @author Bryan Quinn (bquinn@arsdigita.com) +-- @author Jon Salz (jsalz@mit.edu) +-- @creation-date 2000/04/30 +-- @cvs-id apm-create.sql,v 1.21.2.5 2001/01/22 19:10:41 mayoff Exp + +----------------------------- +-- PACKAGE OBJECT -- +----------------------------- + +----------------------------- +-- Knowledge Level -- +----------------------------- + +create table apm_package_types ( + package_key varchar(100) + constraint apm_package_types_p_key_pk primary key, + pretty_name varchar(100) + constraint apm_package_types_pretty_n_nn not null + constraint apm_package_types_pretty_n_un unique, + pretty_plural varchar(100) + constraint apm_package_types_pretty_pl_un unique, + package_uri varchar(1500) + constraint apm_packages_types_p_uri_nn not null + constraint apm_packages_types_p_uri_un unique, + package_type varchar(300) + constraint apm_packages_pack_type_ck + check (package_type in ('apm_application', 'apm_service')), + spec_file_path varchar(1500), + spec_file_mtime integer, + singleton_p boolean default 'f' not null +); + +comment on table apm_package_types is ' + This table holds additional knowledge level attributes for the + apm_package type and its subtypes. +'; + + +comment on column apm_package_types.package_key is ' + The package_key is what we call the package on this system. +'; + +comment on column apm_package_types.package_uri is ' + The package URI indicates where the package can be downloaded and + is a unique identifier for the package. +'; + +comment on column apm_package_types.spec_file_path is ' + The path to the package specification file. +'; + +comment on column apm_package_types.spec_file_mtime is ' + The last time a spec file was modified. This information is maintained in the +database so that if a user changes the specification file by editing the file +(as opposed to using the UI, the system can read the .info file and update +the information in the database appropriately. +'; + +comment on column apm_package_types.singleton_p is ' + Indicates if the package can be used for subsites. If this is set to + ''t'', the package can be enabled for any subsite. Otherwise, it is + restricted to the acs-admin/ subsite. +'; + + +create function inline_0 () +returns integer as ' +begin +-- Create a new object type for packages. + PERFORM acs_object_type__create_type ( + ''apm_package'', + ''Package'', + ''Packages'', + ''acs_object'', + ''APM_PACKAGES'', + ''package_id'', + ''apm_package'', + ''f'', + ''apm_package_types'', + ''apm_package.name'' + ); + + return 0; +end;' language 'plpgsql'; + +select inline_0 (); + +drop function inline_0 (); + + +-- show errors + +create function inline_1 () +returns integer as ' +declare + attr_id acs_attributes.attribute_id%TYPE; +begin +-- Register the meta-data for APM-packages + attr_id := acs_attribute__create_attribute ( + ''apm_package'', + ''package_key'', + ''string'', + ''Package Key'', + ''Package Keys'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package'', + ''package_uri'', + ''string'', + ''Package URI'', + ''Package URIs'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package'', + ''spec_file_path'', + ''string'', + ''Specification File Path'', + ''Specification File Paths'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package'', + ''spec_file_mtime'', + ''number'', + ''Specification File Modified Time'', + ''Specification File Modified Times'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package'', + ''singleton_p'', + ''boolean'', + ''Singleton'', + ''Singletons'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + return 0; +end;' language 'plpgsql'; + +select inline_1 (); + +drop function inline_1 (); + + +-- show errors + +create table apm_packages ( + package_id integer constraint apm_packages_package_id_fk + references acs_objects(object_id) + constraint apm_packages_pack_id_pk primary key, + package_key varchar(100) constraint apm_packages_package_key_fk + references apm_package_types(package_key), + instance_name varchar(300) + constraint apm_packages_inst_name_nn not null, + enabled_p boolean default 'f' +); + +create index apm_packages_package_key_idx on apm_packages (package_key); + +comment on table apm_packages is ' + This table maintains the list of all package instances in the sytem. +'; + +comment on column apm_packages.instance_name is ' + This column enables a name to associated with each instance of package. This enables the storage +of a human-readable distinction between different package instances. This is useful +if a site admin wishes to name an instance of an application, e.g. bboard, for a subsite. The admin +might create one instance, "Boston Public Bboard" for managing public forums for the Boston subsite, +and "Boston Private Bboard" for managing private forums for the Boston subsite. +'; + +comment on column apm_packages.enabled_p is ' + This indicates whether a package instance is enabled or not. Enabling a package instance means that +if a user accesses a URL mapped to the object, the package content will display. +Disabling a package prevents its content from ever being displayed. +'; + +----------------------------- +-- Operational Level -- +----------------------------- + +create table apm_package_versions ( + version_id integer + constraint apm_package_vers_id_pk primary key + constraint apm_package_vers_id_fk + references acs_objects(object_id), + package_key varchar(100) + constraint apm_package_vers_pack_key_nn not null + constraint apm_package_vers_pack_key_fk + references apm_package_types(package_key), + version_name varchar(100) + constraint apm_package_vers_ver_name_nn not null, + version_uri varchar(1500) + constraint apm_package_vers_ver_uri_nn not null + constraint apm_package_vers_ver_uri_un unique, + summary varchar(3000) default '' not null, + description_format varchar(100) + constraint apm_package_vers_desc_for_ck + check (description_format in ('text/html', 'text/plain')), + description text default '' not null, + release_date timestamp, + vendor varchar(500) default '' not null, + vendor_uri varchar(1500) default '' not null, + enabled_p boolean default 'f' + constraint apm_package_vers_enabled_p_nn not null, + installed_p boolean default 'f' + constraint apm_package_vers_inst_p_nn not null, + tagged_p boolean default 'f' + constraint apm_package_vers_tagged_p_nn not null, + imported_p boolean default 'f' + constraint apm_package_vers_imp_p_nn not null, + data_model_loaded_p boolean default 'f' + constraint apm_package_vers_dml_p_nn not null, + cvs_import_results text default '' not null, + activation_date timestamp, + deactivation_date timestamp, + -- FIXME: use this as the blob_id + distribution_tarball integer, + distribution_uri varchar(1500) default '' not null, + distribution_date timestamp, + constraint apm_package_vers_id_name_un unique(package_key, version_name) +); + +comment on table apm_package_versions is ' + The table apm_package_versions contains one row for each version of each package + we know about, e.g., acs-kernel-3.3, acs-kernel-3.3.1, bboard-1.0, + bboard-1.0.1, etc. +'; + +comment on column apm_package_versions.version_name is ' +A version number consists of: + 1.A major version number. + 2.Optionally, up to three minor version numbers. + 3.One of the following: + The letter d, indicating a development-only version. + The letter a, indicating an alpha release. + The letter b, indicating a beta release. + No letter at all, indicating a final release. +In addition, the letters d, a, and b may be followed by another integer, indicating a version within the release. +For those who like regular expressions: + version_number := integer (''.'' integer){0,3} ((''d''|''a''|''b'') integer?)? +So the following is a valid progression for version numbers: + 0.9d, 0.9d1, 0.9a1, 0.9b1, 0.9b2, 0.9, 1.0, 1.0.1, 1.1b1, 1.1 +'; + +comment on column apm_package_versions.version_uri is ' + This column should uniquely identify a package version. This URI should in practice be a URL at which this specific +version can be downloaded. +'; + +comment on column apm_package_versions.summary is ' +Type a brief, one-sentence-or-less summary of the functionality of +your package. The summary should begin with a capital letter +and end with a period. +XXX (bquinn): Move to Content Repository? +'; + +comment on column apm_package_versions.description_format is ' + Must indicate whether the description is plain text or HTML. +'; + +comment on column apm_package_versions.description is ' +Type a one-paragraph description of your package. This is probably analogous +to the first paragraph in your package''s documentation. This is used to describe +the system to users considering installing it. +'; + +comment on column apm_package_versions.release_date is ' +This tracks when the package was released. Releasing a package means +freezing the code and files, creating an archive, and making the +package available for donwload. XXX (bquinn): I''m skeptical about the +usefulness of storing this information here. +'; + +comment on column apm_package_versions.vendor is ' +If the package is being released by a company or some kind of organization, +its name should go here. +'; + +comment on column apm_package_versions.vendor_uri is ' +This should be a URL pointing to the vendor. +'; + +comment on column apm_package_versions.enabled_p is ' + Is the version scheduled to be loaded at startup? +'; + +comment on column apm_package_versions.installed_p is ' + Is the version actually present in the filesystem? +'; + +comment on column apm_package_versions.tagged_p is ' + Have we ever assigned all the files in this version a CVS tag. + XXX (bquinn): deprecated. CVS management should not be through + this table. +'; + +comment on column apm_package_versions.imported_p is ' + Did we perform a vendor import on this version? + XXX (bquinn): deprecated. CVS management should not be through + this table. +'; + +comment on column apm_package_versions.data_model_loaded_p is ' + Have we brought the data model up to date for this version. + XXX (bquinn): deprecated. Its not useful to track this information. +'; + +comment on column apm_package_versions.cvs_import_results is ' + Store the results of an attempted CVS import. + XXX (bquinn): deprecated. CVS management should not be through + this table. +'; + +comment on column apm_package_versions.activation_date is ' + When was the version last enabled? + XXX (bquinn): do we really care about this enough to keep the information around? +'; + +comment on column apm_package_versions.deactivation_date is ' + When was the version last disabled? + XXX (bquinn): do we really care about this enough to keep the information around? +'; + +comment on column apm_package_versions.distribution_tarball is ' + The archive of the distribution. + XXX (bquinn): This should definitely be moved + to the content repository and renamed distribution_archive, or simply + stored in the file system. +'; + +comment on column apm_package_versions.distribution_uri is ' + Where was the distribution tarball downloaded from. +'; + +comment on column apm_package_versions.distribution_date is ' + When was the distribution tarball downloaded. +'; + +-- Metadata for the apm_package_versions object. + +create function inline_2 () +returns integer as ' +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + attr_id := acs_object_type__create_type ( + ''apm_package_version'', + ''Package Version'', + ''Package Versions'', + ''acs_object'', + ''APM_PACKAGE_VERSIONS'', + ''version_id'', + ''APM_PACKAGE_VERSION'', + ''f'', + null, + null + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''package_key'', + ''string'', + ''Package Key'', + ''Package Keys'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''version_name'', + ''string'', + ''Version Name'', + ''Version Names'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''version_uri'', + ''string'', + ''Version URI'', + ''Version URIs'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''summary'', + ''string'', + ''Summary'', + ''Summaries'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''description_format'', + ''string'', + ''Description Format'', + ''Description Formats'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''description'', + ''string'', + ''Description'', + ''Descriptions'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''vendor'', + ''string'', + ''Vendor'', + ''Vendors'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''vendor_uri'', + ''string'', + ''Vendor URI'', + ''Vendor URIs'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''enabled_p'', + ''string'', + ''Enabled'', + ''Enabled'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''activation_date'', + ''date'', + ''Activation Date'', + ''Activation Dates'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''deactivation_date'', + ''string'', + ''Deactivation Date'', + ''Deactivation Dates'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''distribution_uri'', + ''string'', + ''Distribution URI'', + ''Distribution URIs'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_package_version'', + ''distribution_date'', + ''date'', + ''Distribution Date'', + ''Distribution Dates'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + return 0; +end;' language 'plpgsql'; + +select inline_2 (); + +drop function inline_2 (); + + +-- show errors + +-- Who owns a version? +create table apm_package_owners ( + version_id integer constraint apm_package_owners_ver_id_fk references apm_package_versions on delete cascade, + -- if the uri is an email address, it should look like 'mailto:alex@arsdigita.com' + owner_uri varchar(1500) default '' not null, + owner_name varchar(200) + constraint apm_package_owners_name_nn not null, + sort_key integer +); + +create index apm_pkg_owners_version_idx on apm_package_owners (version_id); + +comment on table apm_package_owners is ' + This table tracks all of the owners of a particular package, and their email information. The sort_key column + manages the order of the authors. +'; + +-- Ths view faciliates accessing information about package versions by joining +-- the apm_package_types information and acs_object_types information (which is +-- invariant across versions) with the specific version information. +create view apm_package_version_info as + select v.package_key, t.package_uri, t.pretty_name, 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.enabled_p, v.installed_p, v.tagged_p, v.imported_p, v.data_model_loaded_p, + v.activation_date, v.deactivation_date, +-- dbms_lob.getlength(distribution_tarball) tarball_length, +-- FIXME: + 0 as tarball_length, + distribution_uri, distribution_date + from apm_package_types t, apm_package_versions v + where v.package_key = t.package_key; + + +-- A useful view for simply determining which packages are eanbled. +create view apm_enabled_package_versions as + select * from apm_package_version_info + where enabled_p = 't'; + +create table apm_package_file_types ( + file_type_key varchar(50) + constraint apm_package_file_types_pk primary key, + pretty_name varchar(200) + constraint apm_package_file_types_name_nn not null +); + +comment on table apm_package_file_types is ' + A list of all the different kinds of files that can be part of an APM package. +'; + +create function inline_3 () +returns integer as ' +begin + insert into apm_package_file_types(file_type_key, pretty_name) values(''documentation'', ''Documentation''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''tcl_procs'', ''Tcl procedure library''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''tcl_init'', ''Tcl initialization''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''content_page'', ''Content page''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''package_spec'', ''Package specification''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''data_model'', ''Data model''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''data_model_create'', ''Data model installation''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''data_model_drop'', ''Data model deinstallation''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''data_model_upgrade'', ''Data model upgrade''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''java_code'', ''Java Code''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''template'', ''Template file''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''shell'', ''Shell utility''); + insert into apm_package_file_types(file_type_key, pretty_name) values(''sqlj_code'', ''SQLJ Library''); + + return 0; +end;' language 'plpgsql'; + +select inline_3 (); + +drop function inline_3 (); + + +-- show errors + +-- Which files are contained in a version? +create table apm_package_files ( + file_id integer + constraint apm_package_files_id_pk primary key, + version_id integer constraint apm_package_files_ver_id_fk references apm_package_versions + on delete cascade + constraint apm_package_files_ver_id_nn not null, + path varchar(1500) + constraint apm_package_files_path_nn not null, + file_type varchar(50) constraint apm_package_files_type_fk references apm_package_file_types, + constraint apm_package_files_un unique(version_id, path) +); + +create index apm_pkg_files_file_type_idx on apm_package_files (file_type); + +comment on table apm_package_files is ' + The files that belong to an APM package. We store this information in the database +so that we can identify when a file is missing or added to the filesystem. +'; + +comment on column apm_package_files.path is ' + The relative path of the file underneath the package-root, i.e., + /packages/package-key. For example, packages/address-book/www/index.tcl would have + "www/index.tcl" as a path. +'; + +comment on column apm_package_files.file_type is ' + What kind of file is it? +'; + + +create index apm_package_files_by_path on apm_package_files(path); +create index apm_package_files_by_version on apm_package_files(version_id); + +-- A useful view for combining the package information with the file information. + +create view apm_file_info as + select f.*, p.package_key, 'packages/' || p.package_key || '/' || f.path as full_path + from apm_package_files f, apm_package_versions v, apm_package_types p + where f.version_id = v.version_id + and v.package_key = p.package_key; + + +create table apm_parameters ( + parameter_id integer constraint apm_parameters_fk + references acs_objects(object_id) + constraint apm_parameters_pk primary key, + package_key varchar(100) + constraint apm_pack_param_pack_key_nn not null + constraint apm_pack_param_type_fk + references apm_package_types (package_key), + parameter_name varchar(100) + constraint apm_pack_params_name_nn not null, + description varchar(2000) default '' not null, + section_name varchar(200) default '' not null, + datatype varchar(100) not null + constraint apm_parameter_datatype_ck + check(datatype in ('number', 'string')), + default_value text default '' not null, + min_n_values integer default 1 not null + constraint apm_paramters_min_n_ck + check (min_n_values >= 0), + max_n_values integer default 1 not null + constraint apm_paramters_max_n_ck + check (max_n_values >= 0), + constraint apm_paramters_attr_name_un + unique (parameter_name, package_key), + constraint apm_paramters_n_values_ck + check (min_n_values <= max_n_values) +); + +create index apm_parameters_package_idx on apm_parameters (package_key); + +comment on table apm_parameters is ' + This table stores information about parameters on packages. Every package parameter +is specific to a particular package instance and is queryable with the Tcl call +ad_parameter. +'; + +comment on column apm_parameters.parameter_name is ' + This is the name of the parameter, for example "DebugP." +'; + +comment on column apm_parameters.description is ' + A human readable description of what the parameter is used for. +'; + +comment on column apm_parameters.datatype is ' + Acceptable datatypes for parameters. Currently only numbers and strings. + XXX (bquinn): Integrate with acs objects metadata system. It is not + currently so integrated because of fluctuations with the general + storage mechanism during development. +'; + +comment on column apm_parameters.default_value is ' + The default value that any package instance will inherit unless otherwise + specified. +'; + +comment on column apm_parameters.min_n_values is ' + The minimum number of values that this parameter can take. Zero values means + that the default is always enforced (but is somewhat pointless). One value means that + it can only be set to one value. Increasing this number beyond one enables associating + a list of values with a parameter. + XXX (bquinn): More than one value is not supported by ad_parameter call at this time. +'; + +comment on column apm_parameters.max_n_values is ' +The maximum number of values that any attribute with this datatype + can have. +'; + +create table apm_parameter_values ( + value_id integer constraint apm_parameter_values_fk + references acs_objects(object_id) + constraint apm_parameter_values_pk primary key, + package_id integer constraint apm_pack_values_obj_id_fk + references apm_packages (package_id) on delete cascade, + parameter_id integer constraint apm_pack_values_parm_id_fk + references apm_parameters (parameter_id), + attr_value text default '' not null, + constraint apm_parameter_values_un + unique (package_id, parameter_id) +); + +create index apm_par_vals_parameter_idx on apm_parameter_values (parameter_id); + +comment on table apm_parameter_values is ' + This table holds the values of parameters for package instances. +'; + +comment on column apm_parameter_values.attr_value is ' + This column holds the value for the instance parameter. +'; + +-- Metadata for the apm_parameter and apm_parameter_value system. + +create function inline_4 () +returns integer as ' +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + attr_id := acs_object_type__create_type ( + ''apm_parameter'', + ''Package Parameter'', + ''Package Parameters'', + ''acs_object'', + ''APM_PARAMETERS'', + ''parameter_id'', + ''apm_parameter'', + ''f'', + null, + null + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter'', + ''package_key'', + ''string'', + ''Package Key'', + ''Package Keys'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter'', + ''parameter_name'', + ''string'', + ''Parameter Name'', + ''Parameter Name'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter'', + ''datatype'', + ''string'', + ''Datatype'', + ''Datatypes'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter'', + ''default_value'', + ''string'', + ''Default Value'', + ''Default Values'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter'', + ''min_n_values'', + ''number'', + ''Minimum Number of Values'', + ''Minimum Numer of Values Settings'', + null, + null, + 1, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter'', + ''max_n_values'', + ''string'', + ''Maximum Number of Values'', + ''Maximum Number of Values Settings'', + null, + null, + 1, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + return 0; +end;' language 'plpgsql'; + +select inline_4 (); + +drop function inline_4 (); + + +-- show errors + + +create function inline_5 () +returns integer as ' +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + attr_id := acs_object_type__create_type ( + ''apm_parameter_value'', + ''APM Package Parameter Value'', + ''APM Package Parameter Values'', + ''acs_object'', + ''apm_parameter_values'', + ''value_id'', + ''apm_parameter_value'', + ''f'', + null, + null + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter_value'', + ''package_id'', + ''number'', + ''Package ID'', + ''Package IDs'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter_value'', + ''parameter_id'', + ''number'', + ''Parameter ID'', + ''Parameter IDs'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''apm_parameter_value'', + ''attr_value'', + ''string'', + ''Parameter Value'', + ''Parameter Values'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + return 0; +end;' language 'plpgsql'; + +select inline_5 (); + +drop function inline_5 (); + + +-- show errors + +create table apm_package_dependencies ( + dependency_id integer + constraint apm_package_deps_id_pk primary key, + version_id integer constraint apm_package_deps_version_id_fk references apm_package_versions on delete cascade + constraint apm_package_deps_version_id_nn not null, + dependency_type varchar(20) + constraint apm_package_deps_type_nn not null + constraint apm_package_deps_type_ck check(dependency_type in ('provides','requires')), + service_uri varchar(1500) + constraint apm_package_deps_uri_nn not null, + service_version varchar(100) + constraint apm_package_deps_ver_name_nn not null, + constraint apm_package_deps_un unique(version_id, service_uri) +); + +comment on table apm_package_dependencies is ' + This table indicates what services are provided or required by a particular version. +'; + +comment on column apm_package_dependencies.service_version is ' + The restrictions on service version should match those on apm_package_versions.version_name. +'; + + +create table apm_applications ( + application_id integer + constraint applications_application_id_fk + references apm_packages(package_id) + constraint applications_pk primary key +); + +comment on table apm_applications is ' +This table records data on all of the applications registered in the ACS. +'; + + +create table apm_services ( + service_id integer + constraint services_service_id_fk + references apm_packages(package_id) + constraint services_pk primary key +); + +comment on table apm_services is ' +This table records data on all of the services registered in the ACS. +'; + + +create function inline_6 () +returns integer as ' +declare + dummy integer; +begin +-- Create a new object type for applications. + dummy := acs_object_type__create_type ( + ''apm_application'', + ''Application'', + ''Applications'', + ''apm_package'', + ''apm_applications'', + ''application_id'', + ''apm_application'', + ''f'', + null, + null + ); + + return 0; +end;' language 'plpgsql'; + +select inline_6 (); + +drop function inline_6 (); + + +-- show errors + + +create function inline_7 () +returns integer as ' +declare + dummy integer; +begin +-- Create a new object type for services. + dummy := acs_object_type__create_type ( + ''apm_service'', + ''Service'', + ''Services'', + ''apm_package'', + ''apm_services'', + ''service_id'', + ''apm_service'', + ''f'', + null, + null + ); + + return 0; +end;' language 'plpgsql'; + +select inline_7 (); + +drop function inline_7 (); + + +-- show errors + +-- Public Programmer level API. +-- create or replace package apm +-- as +-- procedure register_package ( +-- package_key in apm_package_types.package_key%TYPE, +-- pretty_name in apm_package_types.pretty_name%TYPE, +-- pretty_plural in apm_package_types.pretty_plural%TYPE, +-- package_uri in apm_package_types.package_uri%TYPE, +-- package_type in apm_package_types.package_type%TYPE, +-- singleton_p in apm_package_types.singleton_p%TYPE +-- default 'f', +-- spec_file_path in apm_package_types.spec_file_path%TYPE +-- default null, +-- spec_file_mtime in apm_package_types.spec_file_mtime%TYPE +-- default null +-- ); +-- +-- function update_package ( +-- package_key in apm_package_types.package_key%TYPE, +-- pretty_name in apm_package_types.pretty_name%TYPE +-- default null, +-- pretty_plural in apm_package_types.pretty_plural%TYPE +-- default null, +-- package_uri in apm_package_types.package_uri%TYPE +-- default null, +-- package_type in apm_package_types.package_type%TYPE +-- default null, +-- singleton_p in apm_package_types.singleton_p%TYPE +-- default null, +-- spec_file_path in apm_package_types.spec_file_path%TYPE +-- default null, +-- spec_file_mtime in apm_package_types.spec_file_mtime%TYPE +-- default null +-- ) return apm_package_types.package_type%TYPE; +-- +-- procedure unregister_package ( +-- package_key in apm_package_types.package_key%TYPE, +-- cascade_p in char default 't' +-- ); +-- +-- function register_p ( +-- package_key in apm_package_types.package_key%TYPE +-- ) return integer; +-- +-- -- Informs the APM that this application is available for use. +-- procedure register_application ( +-- package_key in apm_package_types.package_key%TYPE, +-- pretty_name in apm_package_types.pretty_name%TYPE, +-- pretty_plural in apm_package_types.pretty_plural%TYPE, +-- package_uri in apm_package_types.package_uri%TYPE, +-- singleton_p in apm_package_types.singleton_p%TYPE +-- default 'f', +-- spec_file_path in apm_package_types.spec_file_path%TYPE +-- default null, +-- spec_file_mtime in apm_package_types.spec_file_mtime%TYPE +-- default null +-- ); +-- +-- -- Remove the application from the system. +-- procedure unregister_application ( +-- package_key in apm_package_types.package_key%TYPE, +-- -- Delete all objects associated with this application. +-- cascade_p in char default 'f' +-- ); +-- +-- procedure register_service ( +-- package_key in apm_package_types.package_key%TYPE, +-- pretty_name in apm_package_types.pretty_name%TYPE, +-- pretty_plural in apm_package_types.pretty_plural%TYPE, +-- package_uri in apm_package_types.package_uri%TYPE, +-- singleton_p in apm_package_types.singleton_p%TYPE +-- default 'f', +-- spec_file_path in apm_package_types.spec_file_path%TYPE +-- default null, +-- spec_file_mtime in apm_package_types.spec_file_mtime%TYPE +-- default null +-- ); +-- +-- -- Remove the service from the system. +-- procedure unregister_service ( +-- package_key in apm_package_types.package_key%TYPE, +-- -- Delete all objects associated with this service. +-- cascade_p in char default 'f' +-- ); +-- +-- -- Indicate to APM that a parameter is available to the system. +-- function register_parameter ( +-- parameter_id in apm_parameters.parameter_id%TYPE +-- default null, +-- package_key in apm_parameters.package_key%TYPE, +-- parameter_name in apm_parameters.parameter_name%TYPE, +-- description in apm_parameters.description%TYPE +-- default null, +-- datatype in apm_parameters.datatype%TYPE +-- default 'string', +-- default_value in apm_parameters.default_value%TYPE +-- default null, +-- section_name in apm_parameters.section_name%TYPE +-- default null, +-- min_n_values in apm_parameters.min_n_values%TYPE +-- default 1, +-- max_n_values in apm_parameters.max_n_values%TYPE +-- default 1 +-- ) return apm_parameters.parameter_id%TYPE; +-- +-- function update_parameter ( +-- parameter_id in apm_parameters.parameter_id%TYPE, +-- parameter_name in apm_parameters.parameter_name%TYPE +-- default null, +-- description in apm_parameters.description%TYPE +-- default null, +-- datatype in apm_parameters.datatype%TYPE +-- default 'string', +-- default_value in apm_parameters.default_value%TYPE +-- default null, +-- section_name in apm_parameters.section_name%TYPE +-- default null, +-- min_n_values in apm_parameters.min_n_values%TYPE +-- default 1, +-- max_n_values in apm_parameters.max_n_values%TYPE +-- default 1 +-- ) return apm_parameters.parameter_name%TYPE; +-- +-- function parameter_p( +-- package_key in apm_package_types.package_key%TYPE, +-- parameter_name in apm_parameters.parameter_name%TYPE +-- ) return integer; +-- +-- -- Remove any uses of this parameter. +-- procedure unregister_parameter ( +-- parameter_id in apm_parameters.parameter_id%TYPE +-- default null +-- ); +-- +-- -- Return the value of this parameter for a specific package and parameter. +-- function get_value ( +-- parameter_id in apm_parameter_values.parameter_id%TYPE, +-- package_id in apm_packages.package_id%TYPE +-- ) return apm_parameter_values.attr_value%TYPE; +-- +-- function get_value ( +-- package_id in apm_packages.package_id%TYPE, +-- parameter_name in apm_parameters.parameter_name%TYPE +-- ) return apm_parameter_values.attr_value%TYPE; +-- +-- -- Sets a value for a parameter for a package instance. +-- procedure set_value ( +-- parameter_id in apm_parameter_values.parameter_id%TYPE, +-- package_id in apm_packages.package_id%TYPE, +-- attr_value in apm_parameter_values.attr_value%TYPE +-- ); +-- +-- procedure set_value ( +-- package_id in apm_packages.package_id%TYPE, +-- parameter_name in apm_parameters.parameter_name%TYPE, +-- attr_value in apm_parameter_values.attr_value%TYPE +-- ); +-- +-- +-- end apm; + +-- show errors + +-- create or replace package apm_package +-- as +-- +-- function new ( +-- package_id in apm_packages.package_id%TYPE +-- default null, +-- instance_name in apm_packages.instance_name%TYPE +-- default null, +-- package_key in apm_packages.package_key%TYPE, +-- object_type in acs_objects.object_type%TYPE +-- default 'apm_package', +-- creation_date in acs_objects.creation_date%TYPE +-- default sysdate, +-- creation_user in acs_objects.creation_user%TYPE +-- default null, +-- creation_ip in acs_objects.creation_ip%TYPE +-- default null, +-- context_id in acs_objects.context_id%TYPE +-- default null +-- ) return apm_packages.package_id%TYPE; +-- +-- procedure delete ( +-- package_id in apm_packages.package_id%TYPE +-- ); +-- +-- function singleton_p ( +-- package_key in apm_packages.package_key%TYPE +-- ) return integer; +-- +-- function num_instances ( +-- package_key in apm_package_types.package_key%TYPE +-- ) return integer; +-- +-- function name ( +-- package_id in apm_packages.package_id%TYPE +-- ) return varchar2; +-- +-- -- Enable a package to be utilized by a subsite. +-- procedure enable ( +-- package_id in apm_packages.package_id%TYPE +-- ); +-- +-- procedure disable ( +-- package_id in apm_packages.package_id%TYPE +-- ); +-- +-- function highest_version ( +-- package_key in apm_package_types.package_key%TYPE +-- ) return apm_package_versions.version_id%TYPE; +-- +-- end apm_package; + +-- show errors + +-- create or replace package apm_package_version +-- as +-- function new ( +-- version_id in apm_package_versions.version_id%TYPE +-- default null, +-- package_key in apm_package_versions.package_key%TYPE, +-- version_name in apm_package_versions.version_name%TYPE +-- default null, +-- version_uri in apm_package_versions.version_uri%TYPE, +-- summary in apm_package_versions.summary%TYPE, +-- description_format in apm_package_versions.description_format%TYPE, +-- description in apm_package_versions.description%TYPE, +-- release_date in apm_package_versions.release_date%TYPE, +-- vendor in apm_package_versions.vendor%TYPE, +-- vendor_uri in apm_package_versions.vendor_uri%TYPE, +-- installed_p in apm_package_versions.installed_p%TYPE +-- default 'f', +-- data_model_loaded_p in apm_package_versions.data_model_loaded_p%TYPE +-- default 'f' +-- ) return apm_package_versions.version_id%TYPE; +-- +-- procedure delete ( +-- version_id in apm_packages.package_id%TYPE +-- ); +-- +-- procedure enable ( +-- version_id in apm_package_versions.version_id%TYPE +-- ); +-- +-- procedure disable ( +-- version_id in apm_package_versions.version_id%TYPE +-- ); +-- +-- function edit ( +-- new_version_id in apm_package_versions.version_id%TYPE +-- default null, +-- version_id in apm_package_versions.version_id%TYPE, +-- version_name in apm_package_versions.version_name%TYPE +-- default null, +-- version_uri in apm_package_versions.version_uri%TYPE, +-- summary in apm_package_versions.summary%TYPE, +-- description_format in apm_package_versions.description_format%TYPE, +-- description in apm_package_versions.description%TYPE, +-- release_date in apm_package_versions.release_date%TYPE, +-- vendor in apm_package_versions.vendor%TYPE, +-- vendor_uri in apm_package_versions.vendor_uri%TYPE, +-- installed_p in apm_package_versions.installed_p%TYPE +-- default 'f', +-- data_model_loaded_p in apm_package_versions.data_model_loaded_p%TYPE +-- default 'f' +-- ) return apm_package_versions.version_id%TYPE; +-- +-- -- Add a file to the indicated version. +-- function add_file( +-- file_id in apm_package_files.file_id%TYPE +-- default null, +-- version_id in apm_package_versions.version_id%TYPE, +-- path in apm_package_files.path%TYPE, +-- file_type in apm_package_file_types.file_type_key%TYPE +-- ) return apm_package_files.file_id%TYPE; +-- +-- -- Remove a file from the indicated version. +-- procedure remove_file( +-- version_id in apm_package_versions.version_id%TYPE, +-- path in apm_package_files.path%TYPE +-- ); +-- +-- -- Add an interface provided by this version. +-- function add_interface( +-- interface_id in apm_package_dependencies.dependency_id%TYPE +-- default null, +-- version_id in apm_package_versions.version_id%TYPE, +-- interface_uri in apm_package_dependencies.service_uri%TYPE, +-- interface_version in apm_package_dependencies.service_version%TYPE +-- ) return apm_package_dependencies.dependency_id%TYPE; +-- +-- procedure remove_interface( +-- interface_id in apm_package_dependencies.dependency_id%TYPE +-- ); +-- +-- procedure remove_interface( +-- interface_uri in apm_package_dependencies.service_uri%TYPE, +-- interface_version in apm_package_dependencies.service_version%TYPE, +-- version_id in apm_package_versions.version_id%TYPE +-- ); +-- +-- -- Add a requirement for this version. A requirement is some interface that this +-- -- version depends on. +-- function add_dependency( +-- dependency_id in apm_package_dependencies.dependency_id%TYPE +-- default null, +-- version_id in apm_package_versions.version_id%TYPE, +-- dependency_uri in apm_package_dependencies.service_uri%TYPE, +-- dependency_version in apm_package_dependencies.service_version%TYPE +-- ) return apm_package_dependencies.dependency_id%TYPE; +-- +-- procedure remove_dependency( +-- dependency_id in apm_package_dependencies.dependency_id%TYPE +-- ); +-- +-- procedure remove_dependency( +-- dependency_uri in apm_package_dependencies.service_uri%TYPE, +-- dependency_version in apm_package_dependencies.service_version%TYPE, +-- version_id in apm_package_versions.version_id%TYPE +-- ); +-- +-- -- Given a version_name (e.g. 3.2a), return +-- -- something that can be lexicographically sorted. +-- function sortable_version_name ( +-- version_name in apm_package_versions.version_name%TYPE +-- ) return varchar2; +-- +-- -- Given two version names, return 1 if one > two, -1 if two > one, 0 otherwise. +-- -- Deprecate? +-- function version_name_greater( +-- version_name_one in apm_package_versions.version_name%TYPE, +-- version_name_two in apm_package_versions.version_name%TYPE +-- ) return integer; +-- +-- function upgrade_p( +-- path in apm_package_files.path%TYPE, +-- initial_version_name in apm_package_versions.version_name%TYPE, +-- final_version_name in apm_package_versions.version_name%TYPE +-- ) return integer; +-- +-- procedure upgrade( +-- version_id in apm_package_versions.version_id%TYPE +-- ); +-- +-- end apm_package_version; + +-- show errors + +-- create or replace package apm_package_type +-- as +-- procedure create_type( +-- package_key in apm_package_types.package_key%TYPE, +-- pretty_name in acs_object_types.pretty_name%TYPE, +-- pretty_plural in acs_object_types.pretty_plural%TYPE, +-- package_uri in apm_package_types.package_uri%TYPE, +-- package_type in apm_package_types.package_type%TYPE, +-- singleton_p in apm_package_types.singleton_p%TYPE, +-- spec_file_path in apm_package_types.spec_file_path%TYPE default null, +-- spec_file_mtime in apm_package_types.spec_file_mtime%TYPE default null +-- ); +-- +-- function update_type ( +-- package_key in apm_package_types.package_key%TYPE, +-- pretty_name in acs_object_types.pretty_name%TYPE +-- default null, +-- pretty_plural in acs_object_types.pretty_plural%TYPE +-- default null, +-- package_uri in apm_package_types.package_uri%TYPE +-- default null, +-- package_type in apm_package_types.package_type%TYPE +-- default null, +-- singleton_p in apm_package_types.singleton_p%TYPE +-- default null, +-- spec_file_path in apm_package_types.spec_file_path%TYPE +-- default null, +-- spec_file_mtime in apm_package_types.spec_file_mtime%TYPE +-- default null +-- ) return apm_package_types.package_type%TYPE; +-- +-- procedure drop_type ( +-- package_key in apm_package_types.package_key%TYPE, +-- cascade_p in char default 'f' +-- ); +-- +-- function num_parameters ( +-- package_key in apm_package_types.package_key%TYPE +-- ) return integer; +-- +-- end apm_package_type; + +-- show errors + + + +-- Private APM System API for managing parameter values. +-- create or replace package apm_parameter_value +-- as +-- function new ( +-- value_id in apm_parameter_values.value_id%TYPE default null, +-- package_id in apm_packages.package_id%TYPE, +-- parameter_id in apm_parameter_values.parameter_id%TYPE, +-- attr_value in apm_parameter_values.attr_value%TYPE +-- ) return apm_parameter_values.value_id%TYPE; +-- +-- procedure delete ( +-- value_id in apm_parameter_values.value_id%TYPE default null +-- ); +-- end apm_parameter_value; +-- / +-- show errors +-- +-- create or replace package apm_application +-- as +-- +-- function new ( +-- application_id in acs_objects.object_id%TYPE default null, +-- instance_name in apm_packages.instance_name%TYPE +-- default null, +-- package_key in apm_package_types.package_key%TYPE, +-- object_type in acs_objects.object_type%TYPE +-- default 'apm_application', +-- creation_date in acs_objects.creation_date%TYPE default sysdate, +-- creation_user in acs_objects.creation_user%TYPE default null, +-- creation_ip in acs_objects.creation_ip%TYPE default null, +-- context_id in acs_objects.context_id%TYPE default null +-- ) return acs_objects.object_id%TYPE; +-- +-- procedure delete ( +-- application_id in acs_objects.object_id%TYPE +-- ); +-- +-- end; + +-- show errors + + +-- create or replace package apm_service +-- as +-- +-- function new ( +-- service_id in acs_objects.object_id%TYPE default null, +-- instance_name in apm_packages.instance_name%TYPE +-- default null, +-- package_key in apm_package_types.package_key%TYPE, +-- object_type in acs_objects.object_type%TYPE default 'apm_service', +-- creation_date in acs_objects.creation_date%TYPE default sysdate, +-- creation_user in acs_objects.creation_user%TYPE default null, +-- creation_ip in acs_objects.creation_ip%TYPE default null, +-- context_id in acs_objects.context_id%TYPE default null +-- ) return acs_objects.object_id%TYPE; +-- +-- procedure delete ( +-- service_id in acs_objects.object_id%TYPE +-- ); +-- +-- end; + +-- show errors + +-- create or replace package body apm +-- procedure register_package +create function apm__register_package (varchar,varchar,varchar,varchar,varchar,boolean,varchar,integer) +returns integer as ' +declare + package_key alias for $1; + pretty_name alias for $2; + pretty_plural alias for $3; + package_uri alias for $4; + package_type alias for $5; + singleton_p alias for $6; + spec_file_path alias for $7; + spec_file_mtime alias for $8; +begin + PERFORM apm_package_type__create_type( + package_key, + pretty_name, + pretty_plural, + package_uri, + package_type, + singleton_p, + spec_file_path, + spec_file_mtime + ); + + return 0; +end;' language 'plpgsql'; + + +-- function update_package +create function apm__update_package (varchar,varchar,varchar,varchar,varchar,boolean,varchar,integer) +returns varchar as ' +declare + package_key alias for $1; + pretty_name alias for $2; + pretty_plural alias for $3; + package_uri alias for $4; + package_type alias for $5; + singleton_p alias for $6; + spec_file_path alias for $7; + spec_file_mtime alias for $8; +begin + + return apm_package_type__update_type( + package_key, + pretty_name, + pretty_plural, + package_uri, + package_type, + singleton_p, + spec_file_path, + spec_file_mtime + ); + +end;' language 'plpgsql'; + + +-- procedure unregister_package +create function apm__unregister_package (varchar,boolean) +returns integer as ' +declare + package_key alias for $1; + cascade_p alias for $2; +begin + PERFORM apm_package_type__drop_type( + package_key, + cascade_p + ); + + return 0; +end;' language 'plpgsql'; + + +-- function register_p +create function apm__register_p (varchar) +returns integer as ' +declare + register_p__package_key alias for $1; + v_register_p integer; +begin + select case when count(*) = 0 then 0 else 1 end into v_register_p + from apm_package_types + where package_key = register_p__package_key; + + return v_register_p; + +end;' language 'plpgsql'; + + +-- procedure register_application +create function apm__register_application (varchar,varchar,varchar,varchar,boolean,varchar,integer) +returns integer as ' +declare + package_key alias for $1; + pretty_name alias for $2; + pretty_plural alias for $3; + package_uri alias for $4; + singleton_p alias for $5; + spec_file_path alias for $6; + spec_file_mtime alias for $7; +begin + PERFORM apm__register_package( + package_key, + pretty_name, + pretty_plural, + package_uri, + ''apm_application'', + singleton_p, + spec_file_path, + spec_file_mtime + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure unregister_application +create function apm__unregister_application (varchar,boolean) +returns integer as ' +declare + package_key alias for $1; + cascade_p alias for $2; +begin + PERFORM apm__unregister_package ( + package_key, + cascade_p + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure register_service +create function apm__register_service (varchar,varchar,varchar,varchar,boolean,varchar,integer) +returns integer as ' +declare + package_key alias for $1; + pretty_name alias for $2; + pretty_plural alias for $3; + package_uri alias for $4; + singleton_p alias for $5; + spec_file_path alias for $6; + spec_file_mtime alias for $7; +begin + PERFORM apm__register_package( + package_key, + pretty_name, + pretty_plural, + package_uri, + ''apm_service'', + singleton_p, + spec_file_path, + spec_file_mtime + ); + + return 0; +end;' language 'plpgsql'; + + +-- procedure unregister_service +create function apm__unregister_service (varchar,boolean) +returns integer as ' +declare + package_key alias for $1; + cascade_p alias for $2; +begin + PERFORM apm__unregister_package ( + package_key, + cascade_p + ); + + return 0; +end;' language 'plpgsql'; + + +-- function register_parameter +create function apm__register_parameter (integer,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer) +returns integer as ' +declare + register_parameter__parameter_id alias for $1; + register_parameter__package_key alias for $2; + register_parameter__parameter_name alias for $3; + register_parameter__description alias for $4; + register_parameter__datatype alias for $5; + register_parameter__default_value alias for $6; + register_parameter__section_name alias for $7; + register_parameter__min_n_values alias for $8; + register_parameter__max_n_values alias for $9; + + v_parameter_id apm_parameters.parameter_id%TYPE; + cur_val record; +begin + -- Create the new parameter. + v_parameter_id := acs_object__new( + register_parameter__parameter_id, + ''apm_parameter'', + now(), + null, + null, + null + ); + + insert into apm_parameters + (parameter_id, parameter_name, description, package_key, datatype, + default_value, section_name, min_n_values, max_n_values) + values + (v_parameter_id, register_parameter__parameter_name, + coalesce(register_parameter__description,''''), register_parameter__package_key, + register_parameter__datatype, coalesce(register_parameter__default_value,''''), + coalesce(register_parameter__section_name,''''), register_parameter__min_n_values, + register_parameter__max_n_values); + + -- Propagate parameter to new instances. + for cur_val in select ap.package_id, p.parameter_id, p.default_value + from apm_parameters p left outer join apm_parameter_values v + using (parameter_id), apm_packages ap + where p.package_key = ap.package_key + and v.attr_value is null + and p.package_key = register_parameter__package_key + loop + PERFORM apm__set_value( + cur_val.parameter_id, + cur_val.package_id, + cur_val.default_value + ); + end loop; + + return v_parameter_id; + +end;' language 'plpgsql'; + + +-- function update_parameter +create function apm__update_parameter (integer,varchar,varchar,varchar,varchar,varchar,integer,integer) +returns varchar as ' +declare + update_parameter__parameter_id alias for $1; + update_parameter__parameter_name alias for $2; + update_parameter__description alias for $3; + update_parameter__datatype alias for $4; + update_parameter__default_value alias for $5; + update_parameter__section_name alias for $6; + update_parameter__min_n_values alias for $7; + update_parameter__max_n_values alias for $8; +begin + update apm_parameters + set parameter_name = coalesce(update_parameter__parameter_name, parameter_name), + default_value = coalesce(update_parameter__default_value, default_value), + datatype = coalesce(update_parameter__datatype, datatype), + description = coalesce(update_parameter__description, description), + section_name = coalesce(update_parameter__section_name, section_name), + min_n_values = coalesce(update_parameter__min_n_values, min_n_values), + max_n_values = coalesce(update_parameter__max_n_values, max_n_values) + where parameter_id = update_parameter__parameter_id; + + return parameter_id; + +end;' language 'plpgsql'; + + +-- function parameter_p +create function apm__parameter_p (varchar,varchar) +returns integer as ' +declare + parameter_p__package_key alias for $1; + parameter_p__parameter_name alias for $2; + v_parameter_p integer; +begin + select case when count(*) = 0 then 0 else 1 end into v_parameter_p + from apm_parameters + where package_key = parameter_p__package_key + and parameter_name = parameter_p__parameter_name; + + return v_parameter_p; + +end;' language 'plpgsql'; + + +-- procedure unregister_parameter +create function apm__unregister_parameter (integer) +returns integer as ' +declare + unregister_parameter__parameter_id alias for $1; +begin + delete from apm_parameter_values + where parameter_id = unregister_parameter__parameter_id; + delete from apm_parameters + where parameter_id = unregister_parameter__parameter_id; + PERFORM acs_object__delete(parameter_id); + + return 0; +end;' language 'plpgsql'; + + +-- function id_for_name +create function apm__id_for_name (varchar,varchar) +returns integer as ' +declare + id_for_name__parameter_name alias for $1; + id_for_name__package_key alias for $2; + a_parameter_id apm_parameters.parameter_id%TYPE; +begin + select parameter_id into a_parameter_id + from apm_parameters p + where p.parameter_name = id_for_name__parameter_name and + p.package_key = id_for_name__package_key; + + return a_parameter_id; + +end;' language 'plpgsql'; + + +-- function get_value +create function apm__get_value (integer,integer) +returns varchar as ' +declare + get_value__parameter_id alias for $1; + get_value__package_id alias for $2; + value apm_parameter_values.attr_value%TYPE; +begin + select attr_value into value from apm_parameter_values v + where v.package_id = get_value__package_id + and parameter_id = get_value__parameter_id; + + return value; + +end;' language 'plpgsql'; + + +-- function get_value +create function apm__get_value (integer,varchar) +returns varchar as ' +declare + get_value__package_id alias for $1; + get_value__parameter_name alias for $2; + v_parameter_id apm_parameter_values.parameter_id%TYPE; +begin + select parameter_id into v_parameter_id + from apm_parameters + where parameter_name = get_value__parameter_name + and package_key = (select package_key from apm_packages + where package_id = get_value__package_id); + return apm__get_value( + v_parameter_id, + get_value__package_id + ); + +end;' language 'plpgsql'; + + +-- procedure set_value +create function apm__set_value (integer,integer,varchar) +returns integer as ' +declare + set_value__parameter_id alias for $1; + set_value__package_id alias for $2; + set_value__attr_value alias for $3; + v_value_id apm_parameter_values.value_id%TYPE; +begin + -- Determine if the value exists + select value_id into v_value_id from apm_parameter_values + where parameter_id = set_value__parameter_id + and package_id = set_value__package_id; + update apm_parameter_values set attr_value = set_value__attr_value + where parameter_id = set_value__parameter_id + and package_id = set_value__package_id; + -- exception + if NOT FOUND + then + v_value_id := apm_parameter_value__new( + null, + set_value__package_id, + set_value__parameter_id, + set_value__attr_value + ); + end if; + + return 0; +end;' language 'plpgsql'; + + +-- procedure set_value +create function apm__set_value (integer,varchar,varchar) +returns integer as ' +declare + set_value__package_id alias for $1; + set_value__parameter_name alias for $2; + set_value__attr_value alias for $3; + v_parameter_id apm_parameter_values.parameter_id%TYPE; +begin + select parameter_id into v_parameter_id + from apm_parameters + where parameter_name = set_value__parameter_name + and package_key = (select package_key from apm_packages + where package_id = set_value__package_id); + + if NOT FOUND + then + raise EXCEPTION ''%: %'', -20000, ''The specified package '' + || set_value__package_id || '' does not exist in the system.''; + end if; + + PERFORM apm__set_value( + v_parameter_id, + set_value__package_id, + set_value__attr_value + ); + + return 0; +end;' language 'plpgsql'; + + + +-- show errors + +-- create or replace package body apm_package +-- procedure initialize_parameters +create function apm_package__initialize_parameters (integer,varchar) +returns integer as ' +declare + ip__package_id alias for $1; + ip__package_key alias for $2; + v_value_id apm_parameter_values.value_id%TYPE; + cur_val record; +begin + -- need to initialize all params for this type + for cur_val in select parameter_id, default_value + from apm_parameters + where package_key = ip__package_key + loop + v_value_id := apm_parameter_value__new( + null, + ip__package_id, + cur_val.parameter_id, + cur_val.default_value + ); + end loop; + + return 0; +end;' language 'plpgsql'; + + +-- function new +create function apm_package__new (integer,varchar,varchar,varchar,timestamp,integer,varchar,integer) +returns integer as ' +declare + new__package_id alias for $1; + new__instance_name alias for $2; + new__package_key alias for $3; + new__object_type alias for $4; + new__creation_date alias for $5; + new__creation_user alias for $6; + new__creation_ip alias for $7; + new__context_id alias for $8; + v_singleton_p integer; + v_package_type apm_package_types.package_type%TYPE; + v_num_instances integer; + v_package_id apm_packages.package_id%TYPE; + v_instance_name apm_packages.instance_name%TYPE; +begin + v_singleton_p := apm_package__singleton_p( + new__package_key + ); + v_num_instances := apm_package__num_instances( + new__package_key + ); + + if v_singleton_p = 1 and v_num_instances >= 1 then + select package_id into v_package_id + from apm_packages + where package_key = new__package_key; + + return v_package_id; + else + v_package_id := acs_object__new( + new__package_id, + new__object_type, + new__creation_date, + new__creation_user, + new__creation_ip, + new__context_id + ); + if instance_name is null then + v_instance_name := new__package_key || '' '' || v_package_id; + else + v_instance_name := new__instance_name; + end if; + + select package_type into v_package_type + from apm_package_types + where package_key = new__package_key; + + insert into apm_packages + (package_id, package_key, instance_name) + values + (v_package_id, new__package_key, v_instance_name); + + if v_package_type = ''apm_application'' then + insert into apm_applications + (application_id) + values + (v_package_id); + else + insert into apm_services + (service_id) + values + (v_package_id); + end if; + + PERFORM apm_package__initialize_parameters( + v_package_id, + new__package_key + ); + + return v_package_id; + + end if; +end;' language 'plpgsql'; + +create function apm_package__delete (integer) returns integer as ' +declare + delete__package_id alias for $1; + cur_val record; +begin + -- Delete all parameters. + for cur_val in select value_id from apm_parameter_values + where package_id = delete__package_id loop + PERFORM apm_parameter_value__delete(cur_val.value_id); + end loop; + + delete from apm_applications where application_id = delete__package_id; + delete from apm_services where service_id = delete__package_id; + delete from apm_packages where package_id = delete__package_id; + -- Delete the site nodes for the objects. + for cur_val in select node_id from site_nodes + where object_id = delete__package_id loop + PERFORM site_node__delete(cur_val.node_id); + end loop; + -- Delete the object. + PERFORM acs_object__delete ( + delete__package_id + ); + + return 0; +end;' language 'plpgsql'; + +create function apm_package__singleton_p (varchar) returns integer as ' +declare + singleton_p__package_key alias for $1; + v_singleton_p integer; +begin + select 1 into v_singleton_p + from apm_package_types + where package_key = singleton_p__package_key + and singleton_p = ''t''; + + if NOT FOUND then + return 0; + else + return v_singleton_p; + end if; +end;' language 'plpgsql'; + +create function apm_package__num_instances (varchar) returns integer as ' +declare + num_instances__package_key alias for $1; + v_num_instances integer; +begin + select count(*) into v_num_instances + from apm_packages + where package_key = num_instances__package_key; + + -- exception + if NOT FOUND then + return 0; + else + return v_num_instances; + end if; + +end;' language 'plpgsql'; + +create function apm_package__name (integer) returns varchar as ' +declare + name__package_id alias for $1; + v_result apm_packages.instance_name%TYPE; +begin + select instance_name into v_result + from apm_packages + where package_id = name__package_id; + + return v_result; + +end;' language 'plpgsql'; + +create function apm_package__enable (integer) returns integer as ' +declare + enable__package_id alias for $1; +begin + update apm_packages + set enabled_p = ''t'' + where package_id = enable__package_id; + + return 0; +end;' language 'plpgsql'; + +create function apm_package__disable (integer) returns integer as ' +declare + disable__package_id alias for $1; +begin + update apm_packages + set enabled_p = ''f'' + where package_id = disable__package_id; + + returns 0; +end;' language 'plpgsql'; + +create 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'; + + +-- create or replace package body apm_package_version +create function apm_package_version__new (integer,varchar,varchar,varchar,varchar,varchar,varchar,timestamp,varchar,varchar,boolean,boolean) returns integer as ' +declare + apm_pkg_ver__version_id alias for $1; + apm_pkg_ver__package_key alias for $2; + apm_pkg_ver__version_name alias for $3; + 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__installed_p alias for $11; + apm_pkg_ver__data_model_loaded_p alias for $12; + v_version_id apm_package_versions.version_id%TYPE; +begin + if apm_pkg_ver__version_id is null then + select acs_object_id_seq.nextval + 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, 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, coalesce(apm_pkg_ver__summary,''''), + apm_pkg_ver__description_format, coalesce(apm_pkg_ver__description,''''), + apm_pkg_ver__release_date, coalesce(apm_pkg_ver__vendor,''''), coalesce(apm_pkg_ver__vendor_uri,''''), + apm_pkg_ver__installed_p, apm_pkg_ver__data_model_loaded_p); + + return v_version_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function apm_package_version__delete (integer) +returns integer as ' +declare + delete_version_id alias for $1; +begin + delete from apm_package_owners + where version_id = delete__version_id; + + delete from apm_package_files + where version_id = delete__version_id; + + delete from apm_package_dependencies + where version_id = delete__version_id; + + delete from apm_package_versions + where version_id = delete__version_id; + + PERFORM acs_object__delete(delete__version_id); + + return 0; +end;' language 'plpgsql'; + + +-- procedure enable +create function apm_package_version__enable (integer) +returns integer as ' +declare + enable__version_id alias for $1; +begin + update apm_package_versions set enabled_p = ''t'' + where version_id = enable__version_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure disable +create function apm_package_version__disable (integer) +returns integer as ' +declare + disable_version_id alias for $1; +begin + update apm_package_versions + set enabled_p = ''f'' + where version_id = disable__version_id; + + return 0; +end;' language 'plpgsql'; + + +-- function copy +create function apm_package_version__copy (integer,integer,varchar,varchar) +returns integer as ' +declare + copy__version_id alias for $1; + copy__new_version_id alias for $2; + copy__new_version_name alias for $3; + copy__new_version_uri alias for $4; + v_version_id integer; +begin + v_version_id := acs_object__new( + 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) + select v_version_id, package_key, copy__new_version_name, + copy__new_version_uri, summary, description_format, description, + release_date, vendor, vendor_uri + 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 acs_object_id_seq.nextval, 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) + select acs_object_id_seq.nextval, v_version_id, path, file_type + from apm_package_files + where version_id = copy__version_id; + + 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; + + return v_version_id; + +end;' language 'plpgsql'; + + +-- function edit +create function apm_package_version__edit (integer,integer,varchar,varchar,varchar,varchar,varchar,timestamp,varchar,varchar,char,char) +returns integer as ' +declare + edit__new_version_id alias for $1; + edit__version_id alias for $2; + edit__version_name alias for $3; + 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__installed_p alias for $11; + edit__data_model_loaded_p alias for $12; + 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 + ); + 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, + 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'; + + +-- function add_file +create function apm_package_version__add_file (integer,integer,varchar,varchar) +returns integer as ' +declare + add_file__file_id alias for $1; + add_file__version_id alias for $2; + add_file__path alias for $3; + add_file__file_type alias for $4; + v_file_id apm_package_files.file_id%TYPE; + v_file_exists_p integer; +begin + select file_id into v_file_id from apm_package_files + where version_id = add_file__version_id + and path = add_file__path; + + if NOT FOUND + then + if add_file__file_id is null then + select acs_object_id_seq.nextval into v_file_id from dual; + else + v_file_id := add_file__file_id; + end if; + + insert into apm_package_files + (file_id, version_id, path, file_type) + values + (v_file_id, add_file__version_id, add_file__path, add_file__file_type); + end if; + + return v_file_id; + +end;' language 'plpgsql'; + + +-- procedure remove_file +create function apm_package_version__remove_file (integer,varchar) +returns integer as ' +declare + remove_file__version_id alias for $1; + remove_file__path alias for $2; +begin + delete from apm_package_files + where version_id = remove_file__version_id + and path = remove_file__path; + + return 0; +end;' language 'plpgsql'; + + +-- function add_interface +create function apm_package_version__add_interface (integer,integer,varchar,varchar) +returns integer as ' +declare + add_interface__interface_id alias for $1; + add_interface__version_id alias for $2; + add_interface__interface_uri alias for $3; + add_interface__interface_version alias for $4; + v_dep_id apm_package_dependencies.dependency_id%TYPE; +begin + if add_interface__interface_id is null then + select acs_object_id_seq.nextval into v_dep_id from dual; + else + v_dep_id := add_interface__interface_id; + end if; + + insert into apm_package_dependencies + (dependency_id, version_id, dependency_type, service_uri, service_version) + values + (v_dep_id, add_interface__version_id, ''provides'', add_interface__interface_uri, + add_interface__interface_version); + + return v_dep_id; + +end;' language 'plpgsql'; + + +-- procedure remove_interface +create function apm_package_version__remove_interface (integer) +returns integer as ' +declare + remove_interface__interface_id alias for $1; +begin + delete from apm_package_dependencies + where dependency_id = remove_interface__interface_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure remove_interface +create function apm_package_version__remove_interface (varchar,varchar,integer) +returns integer as ' +declare + remove_interface__interface_uri alias for $1; + remove_interface__interface_version alias for $2; + remove_interface__version_id alias for $3; + v_dep_id apm_package_dependencies.dependency_id%TYPE; +begin + select dependency_id into v_dep_id from apm_package_dependencies + where service_uri = remove_interface__interface_uri + and interface_version = remove_interface__interface_version; + PERFORM apm_package_version__remove_interface(v_dep_id); + + return 0; +end;' language 'plpgsql'; + + +-- function add_dependency +create function apm_package_version__add_dependency (integer,integer,varchar,varchar) +returns integer as ' +declare + add_dependency__dependency_id alias for $1; + add_dependency__version_id alias for $2; + add_dependency__dependency_uri alias for $3; + add_dependency__dependency_version alias for $4; + v_dep_id apm_package_dependencies.dependency_id%TYPE; +begin + if add_dependency__dependency_id is null then + select acs_object_id_seq.nextval into v_dep_id from dual; + else + v_dep_id := add_dependency__dependency_id; + end if; + + insert into apm_package_dependencies + (dependency_id, version_id, dependency_type, service_uri, service_version) + values + (v_dep_id, add_dependency__version_id, ''requires'', add_dependency__dependency_uri, + add_dependency__dependency_version); + + return v_dep_id; + +end;' language 'plpgsql'; + + +-- procedure remove_dependency +create function apm_package_version__remove_dependency (integer) +returns integer as ' +declare + remove_dependency__dependency_id alias for $1; +begin + delete from apm_package_dependencies + where dependency_id = remove_dependency__dependency_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure remove_dependency +create function apm_package_version__remove_dependency (varchar,varchar,integer) +returns integer as ' +declare + remove_dependency__dependency_uri alias for $1; + remove_dependency__dependency_version alias for $2; + remove_dependency__version_id alias for $3; + v_dep_id apm_package_dependencies.dependency_id%TYPE; +begin + select dependency_id into v_dep_id from apm_package_dependencies + where service_uri = remove_dependency__dependency_uri + and service_version = remove_dependency__dependency_version; + PERFORM apm_package_version__remove_dependency(v_dep_id); + + return 0; +end;' language 'plpgsql'; + + +-- function sortable_version_name +create function apm_package_version__sortable_version_name (varchar) +returns varchar as ' +declare + version_name alias for $1; + a_start integer; + a_end integer; + a_order varchar(1000); + a_char boolean; + a_seen_letter boolean default ''f''; +begin + a_start := 1; + loop + a_end := a_start; + + -- keep incrementing a_end until we run into a non-number + while substr(version_name, a_end, 1) >= ''0'' and substr(version_name, a_end, 1) <= ''9'' loop + a_end := a_end + 1; + end loop; + if a_end = a_start then + return -1; + -- raise_application_error(-20000, ''Expected number at position '' || a_start); + end if; + if a_end - a_start > 4 then + return -1; + -- raise_application_error(-20000, ''Numbers within versions can only be up to 4 digits long''); + end if; + + -- zero-pad and append the number + a_order := a_order || substr(''0000'', 1, 4 - (a_end - a_start)) || + substr(version_name, a_start, a_end - a_start) || ''.''; + if a_end > length(version_name) then + -- end of string - we''re outta here + if a_seen_letter = ''f'' then + -- append the "final" suffix if there haven''t been any letters + -- so far (i.e., not development/alpha/beta) + a_order := a_order || '' 3F.''; + end if; + return a_order; + end if; + + -- what''s the next character? if a period, just skip it + a_char := substr(version_name, a_end, 1); + if a_char = ''.'' then + null; + else + -- if the next character was a letter, append the appropriate characters + if a_char = ''d'' then + a_order := a_order || '' 0D.''; + else if a_char = ''a'' then + a_order := a_order || '' 1A.''; + else if a_char = ''b'' then + a_order := a_order || '' 2B.''; + end if; end if; end if; + + -- can''t have something like 3.3a1b2 - just one letter allowed! + if a_seen_letter = ''t'' then + return -1; + -- raise_application_error(-20000, ''Not allowed to have two letters in version name '''''' + -- || version_name || ''''''''); + end if; + a_seen_letter := ''t''; + + -- end of string - we''re done! + if a_end = length(version_name) then + return a_order; + end if; + end if; + a_start := a_end + 1; + end loop; + +end;' language 'plpgsql'; + + +-- function version_name_greater +create function apm_package_version__version_name_greater (varchar,varchar) +returns integer as ' +declare + version_name_one alias for $1; + version_name_two alias for $2; +begin + a_order_a := apm_package_version__sortable_version_name(version_name_one); + a_order_b := apm_package_version__sortable_version_name(version_name_two); + if a_order_a < a_order_b then + return -1; + else if a_order_a > a_order_b then + return 1; + end if; end if; + + return 0; +end;' language 'plpgsql'; + +-- function upgrade_p +create function apm_package_version__upgrade_p (varchar,varchar,varchar) +returns integer as ' +declare + upgrade_p__path alias for $1; + upgrade_p__initial_version_name alias for $2; + upgrade_p__final_version_name alias for $3; + v_pos1 integer; + v_pos2 integer; + v_tmp apm_package_files.path%TYPE; + v_path apm_package_files.path%TYPE; + v_version_from apm_package_versions.version_name%TYPE; + v_version_to apm_package_versions.version_name%TYPE; +begin + + -- Set v_path to the tail of the path (the file name). + v_path := substr(upgrade_p__path, instr(upgrade_p__path, ''/'', -1) + 1); + + -- Remove the extension, if it''s .sql. + v_pos1 := position(''.'' in v_path); + if v_pos1 > 0 and substr(v_path, v_pos1) = ''.sql'' then + v_path := substr(v_path, 1, v_pos1 - 1); + end if; + + -- Figure out the from/to version numbers for the individual file. + v_pos1 := instr(v_path, ''-'', -1, 2); + v_pos2 := instr(v_path, ''-'', -1); + if v_pos1 = 0 or v_pos2 = 0 then + -- There aren''t two hyphens in the file name. Bail. + return 0; + end if; + + v_version_from := substr(v_path, v_pos1 + 1, v_pos2 - v_pos1 - 1); + v_version_to := substr(v_path, v_pos2 + 1); + + if apm_package_version__version_name_greater(upgrade_p__initial_version_name, v_version_from) <= 0 and + apm_package_version__version_name_greater(upgrade_p__final_version_name, v_version_to) >= 0 then + return 1; + end if; + + return 0; + -- exception when others then + -- Invalid version number. + -- return 0; + +end;' language 'plpgsql'; + + +-- procedure upgrade +create function apm_package_version__upgrade (integer) +returns integer as ' +declare + upgrade__version_id alias for $1; +begin + update apm_package_versions + set enabled_p = ''f'', + installed_p = ''f'' + where package_key = (select package_key from apm_package_versions + where version_id = upgrade__version_id); + update apm_package_versions + set enabled_p = ''t'', + installed_p = ''t'' + where version_id = upgrade__version_id; + + return 0; +end;' language 'plpgsql'; + + + +-- show errors + +-- create or replace package body apm_package_type +-- procedure create_type +create function apm_package_type__create_type (varchar,varchar,varchar,varchar,varchar,boolean,varchar,integer) +returns integer as ' +declare + create_type__package_key alias for $1; + create_type__pretty_name alias for $2; + create_type__pretty_plural alias for $3; + create_type__package_uri alias for $4; + create_type__package_type alias for $5; + create_type__singleton_p alias for $6; + create_type__spec_file_path alias for $7; + create_type__spec_file_mtime alias for $8; +begin + insert into apm_package_types + (package_key, pretty_name, pretty_plural, package_uri, package_type, + spec_file_path, spec_file_mtime, singleton_p) + values + (create_type__package_key, create_type__pretty_name, create_type__pretty_plural, + create_type__package_uri, create_type__package_type, create_type__spec_file_path, + create_type__spec_file_mtime, create_type__singleton_p); + + return 0; +end;' language 'plpgsql'; + + +-- function update_type +create function apm_package_type__update_type (varchar,varchar,varchar,varchar,varchar,boolean,varchar,integer) +returns varchar as ' +declare + update_type__package_key alias for $1; + update_type__pretty_name alias for $2; + update_type__pretty_plural alias for $3; + update_type__package_uri alias for $4; + update_type__package_type alias for $5; + update_type__singleton_p alias for $6; + update_type__spec_file_path alias for $7; + update_type__spec_file_mtime alias for $8; +begin + UPDATE apm_package_types SET + pretty_name = coalesce(update_type__pretty_name, pretty_name), + pretty_plural = coalesce(update_type__pretty_plural, pretty_plural), + package_uri = coalesce(update_type__package_uri, package_uri), + package_type = coalesce(update_type__package_type, package_type), + spec_file_path = coalesce(update_type__spec_file_path, spec_file_path), + spec_file_mtime = coalesce(update_type__spec_file_mtime, spec_file_mtime), + singleton_p = coalesce(update_type__singleton_p, singleton_p) + where package_key = update_type__package_key; + + return update_type__package_key; + +end;' language 'plpgsql'; + + +-- procedure drop_type +create function apm_package_type__drop_type (varchar,boolean) +returns integer as ' +declare + drop_type__package_key alias for $1; + drop_type__cascade_p alias for $2; + cur_val record; +begin + if drop_type__cascade_p = ''t'' then + for cur_val in select package_id + from apm_packages + where package_key = drop_type__package_key + loop + PERFORM apm_package__delete( + cur_val.package_id + ); + end loop; + -- Unregister all parameters. + for cur_val in select parameter_id from apm_parameters + where package_key = drop_type__package_key + loop + PERFORM apm__unregister_parameter(cur_val.parameter_id); + end loop; + + -- Unregister all versions + for cur_val in select version_id from apm_package_versions + where package_key = drop_type__package_key + loop + PERFORM apm_package_version__delete(cur_val.version_id); + end loop; + end if; + delete from apm_package_types + where package_key = drop_type__package_key; + + return 0; +end;' language 'plpgsql'; + + +-- function num_parameters +create function apm_package_type__num_parameters (varchar) +returns integer as ' +declare + num_parameters__package_key alias for $1; + v_count integer; +begin + select count(*) into v_count + from apm_parameters + where package_key = num_parameters__package_key; + + return v_count; + +end;' language 'plpgsql'; + + + + + +-- show errors + +-- create or replace package body apm_parameter_value +-- function new +create function apm_parameter_value__new (integer,integer,integer,varchar) +returns integer as ' +declare + new__value_id alias for $1; + new__package_id alias for $2; + new__parameter_id alias for $3; + new__attr_value alias for $4; + v_value_id apm_parameter_values.value_id%TYPE; +begin + v_value_id := acs_object__new( + new__value_id, + ''apm_parameter_value'', + now(), + null, + null, + null + ); + insert into apm_parameter_values + (value_id, package_id, parameter_id, attr_value) + values + (v_value_id, new__package_id, new__parameter_id, coalesce(new__attr_value,'''')); + + return v_value_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function apm_parameter_value__delete (integer) +returns integer as ' +declare + delete__value_id alias for $1; +begin + delete from apm_parameter_values + where value_id = delete__value_id; + PERFORM acs_object__delete(delete__value_id); + + return 0; +end;' language 'plpgsql'; + + +-- function new +create function apm_application__new (integer,varchar,varchar,varchar,timestamp,integer,varchar,integer) +returns integer as ' +declare + application_id alias for $1; + instance_name alias for $2; + package_key alias for $3; + object_type alias for $4; + creation_date alias for $5; + creation_user alias for $6; + creation_ip alias for $7; + context_id alias for $8; + v_application_id integer; +begin + v_application_id := apm_package__new ( + application_id, + instance_name, + package_key, + object_type, + creation_date, + creation_user, + creation_ip, + context_id + ); + + return v_application_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function apm_application__delete (integer) +returns integer as ' +declare + delete__application_id alias for $1; +begin + delete from apm_applications + where application_id = delete__application_id; + PERFORM apm_package__delete( + delete__application_id + ); + + return 0; +end;' language 'plpgsql'; + + + +-- show errors + +-- create or replace package body apm_service +-- function new +create function apm_service__new (integer,varchar,varchar,varchar,timestamp,integer,varchar,integer) +returns integer as ' +declare + service_id alias for $1; + instance_name alias for $2; + package_key alias for $3; + object_type alias for $4; + creation_date alias for $5; + creation_user alias for $6; + creation_ip alias for $7; + context_id alias for $8; + v_service_id integer; +begin + v_service_id := apm_package__new ( + service_id, + instance_name, + package_key, + object_type, + creation_date, + creation_user, + creation_ip, + context_id + ); + + return v_service_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function apm_service__delete (integer) +returns integer as ' +declare + delete__service_id alias for $1; +begin + delete from apm_services + where service_id = delete__service_id; + PERFORM apm_package__delete( + delete__service_id + ); + + return 0; +end;' language 'plpgsql'; + + + +-- show errors Index: openacs-4/packages/acs-kernel/sql/postgresql/apm-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/apm-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/apm-drop.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,65 @@ +-- Uninstall file for the data model created by 'apm-create.sql' +-- +-- @author Bryan Quinn (bquinn) +-- @creation-date Mon Sep 18 16:46:56 2000 +-- +-- apm-drop.sql,v 1.6 2000/10/24 22:26:19 bquinn Exp +-- +\t +select drop_package('apm_service'); +select drop_package('apm_application'); +select drop_package('apm_parameter_value'); +select drop_package('apm_package_type'); +select drop_package('apm_package_version'); +select drop_package('apm_package'); +select drop_package('apm'); +drop table apm_package_dependencies; +drop table apm_parameter_values; +drop table apm_parameters; +drop view apm_file_info; +drop index apm_package_files_by_version; +drop index apm_package_files_by_path; +drop table apm_package_files; +drop table apm_package_file_types; +drop view apm_enabled_package_versions; +drop view apm_package_version_info; +drop table apm_package_owners; +drop table apm_package_versions; +drop table apm_services; +drop table apm_applications; +drop table apm_packages; +drop table apm_package_types; + +create function inline_0 () returns integer as ' +begin + PERFORM acs_object_type__drop_type ( + ''apm_package'', ''f'' + ); + + PERFORM acs_object_type__drop_type ( + ''apm_application'', ''f'' + ); + + PERFORM acs_object_type__drop_type ( + ''apm_service'', ''f'' + ); + + PERFORM acs_object_type__drop_type ( + ''apm_package_version'', ''f'' + ); + + PERFORM acs_object_type__drop_type ( + ''apm_parameter_value'', ''f'' + ); + + PERFORM acs_object_type__drop_type ( + ''apm_parameter'', ''f'' + ); + + return null; +end;' language 'plpgsql'; + +select inline_0 (); + +drop function inline_0 (); +\t Index: openacs-4/packages/acs-kernel/sql/postgresql/community-core-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/community-core-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/community-core-create.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,725 @@ +-- +-- acs-kernel/sql/community-core-create.sql +-- +-- Abstractions fundamental to any online community (or information +-- system, in general), derived in large part from the ACS 3.x +-- community-core data model by Philip Greenspun (philg@mit.edu), from +-- the ACS 3.x user-groups data model by Tracy Adams (teadams@mit.edu) +-- from Chapter 3 (The Enterprise and Its World) of David Hay's +-- book _Data_Model_Patterns_, and from Chapter 2 (Accountability) +-- of Martin Fowler's book _Analysis_Patterns_. +-- +-- @author Michael Yoon (michael@arsdigita.com) +-- @author Rafael Schloming (rhs@mit.edu) +-- @author Jon Salz (jsalz@mit.edu) +-- +-- @creation-date 2000-05-18 +-- +-- @cvs-id community-core-create.sql,v 1.11.2.2 2001/01/12 22:49:48 mbryzek Exp +-- + +-- HIGH PRIORITY: +-- +-- * What can subtypes add to the specification of supertype +-- attributes? Extra constraints like "not null"? What about +-- "storage"? Can a subtype override how a given attribute is +-- stored? +-- +-- * Can we realistically revoke INSERT and UPDATE permission on the +-- tables (users, persons, etc.) and make people use the PL/SQL API? +-- One downside is that it would then be difficult or impossible to +-- do things like "update ... set ... where ..." directly, without +-- creating a PL/SQL procedure to do it. +-- +-- * Figure out how to migrate from ACS 3.x users, user_groups, +-- user_group_types, etc. to ACS 4.0 objects/parties/users/organizations; +-- also need to consider general_* and site_wide_* tables +-- (Rafi and Luke) +-- +-- * Take an inventory of acs-kernel tables and other objects (some of which +-- may still be in /www/doc/sql/) and create their ACS 4 analogs, including +-- mapping over all general_* and site_wide_* data models, and make +-- appropriate adjustments to code +-- (Rafi and Yon/Luke/?). +-- +-- * Create magic users: system and anonymous (do we actually need these?) +-- +-- * Define and implement APIs +-- +-- * Figure out user classes, e.g., treat "the set of parties that +-- have relationship X to object Y" as a party in its own right +-- +-- * Explain why acs_rel_types, acs_rel_rules, and acs_rels are not +-- merely replicating the functionality of a relational database. +-- +-- * acs_attribute_type should impose some rules on the min_n_values +-- and max_n_values columns of acs_attributes, e.g., it doesn't +-- really make sense for a boolean attribute to have more than +-- one value +-- +-- * Add support for default values to acs_attributes. +-- +-- * Add support for instance-specific attributes (e.g., +-- user_group_member_fields) +-- +-- MEDIUM PRIORITY: +-- +-- * Read-only attributes? +-- +-- * Do we need to store metadata about enumerations and valid ranges +-- or should we query the Oracle data dictionary for info on check +-- constraints? +-- +-- * Create a "user_group_type" (an object_type with "organization" +-- as its supertype (do we need this?) +-- +-- * Add in ancestor permission view, assuming that we'll use a +-- magical rel_type: "acs_acl"? +-- +-- * How do we get all attribute values for objects of a specific +-- type? "We probably want some convention or standard way for +-- providing a view that joins supertypes and a type. This could +-- be automatically generated through metadata, or it could simply +-- be a convention." - Rafi +-- +-- LOW PRIORITY: +-- +-- * Formalize Rafi's definition of an "object": "A collection of rows +-- identified by an object ID for which we maintain metadata" or +-- something like that. +-- +-- * "We definitely need some standard way of extending a supertype into +-- a subtype, and 'deleting' a subtype into a supertype. This will be +-- needed when we want to transform a 'person' into a registered +-- user, and do 'nuke user' but keep around the user's contributed +-- content and associate it with the 'person' part of that user. This +-- actually works quite nicely with standard oracle inheritance since +-- you can just insert or delete a row in the subtype table and +-- mutate the object type." - Rafi +-- +-- ACS 4.1: +-- +-- * Figure out what to do with pretty names (message catalog) +-- +-- COMPLETED: +-- +-- * Create magic parties: all_users (or just use null party_id?) +-- and registered_users +-- +-- * Test out relationship attributes (making "relationship" an +-- acs_object_type) +-- +-- * Create magic object_types (object, party, person, user, +-- organization) including attrs and rels +-- +-- * Create constraints for creation_user and modifying_user + +create function inline_0 () +returns integer as ' +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + -- + -- Party: the supertype of person and organization + -- + PERFORM acs_object_type__create_type ( + ''party'', + ''Party'', + ''Parties'', + ''acs_object'', + ''parties'', + ''party_id'', + ''party'', + ''f'', + null, + ''party.name'' + ); + + attr_id := acs_attribute__create_attribute ( + ''party'', + ''email'', + ''string'', + ''Email Address'', + ''Email Addresses'', + null, + null, + null, + 0, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''party'', + ''url'', + ''string'', + ''URL'', + ''URLs'', + null, + null, + null, + 0, + 1, + null, + ''type_specific'', + ''f'' + ); + + -- + -- Person: the supertype of user + -- + attr_id := acs_object_type__create_type ( + ''person'', + ''Person'', + ''People'', + ''party'', + ''persons'', + ''person_id'', + ''person'', + ''f'', + null, + ''person.name'' + ); + + attr_id := acs_attribute__create_attribute ( + ''person'', + ''first_names'', + ''string'', + ''First Names'', + ''First Names'', + null, + null, + null, + 0, + 1, + null, + ''type_specific'', + ''f'' + ); + + attr_id := acs_attribute__create_attribute ( + ''person'', + ''last_name'', + ''string'', + ''Last Name'', + ''Last Names'', + null, + null, + null, + 0, + 1, + null, + ''type_specific'', + ''f'' + ); + -- + -- User: people who have registered in the system + -- + attr_id := acs_object_type__create_type ( + ''user'', + ''User'', + ''Users'', + ''person'', + ''users'', + ''user_id'', + ''acs_user'', + ''f'', + null, + null + ); + + + return 0; +end;' language 'plpgsql'; + +select inline_0 (); + +drop function inline_0 (); + + +-- show errors + +-- ****************************************************************** +-- * OPERATIONAL LEVEL +-- ****************************************************************** + +create table parties ( + party_id integer not null + constraint parties_party_id_fk references + acs_objects (object_id) + constraint parties_pk primary key, + email varchar(100) + constraint parties_email_un unique, + url varchar(200) default '' not null +); + +comment on table parties is ' + Party is the supertype of person and organization. It exists because + many other types of object can have relationships to parties. +'; + +comment on column parties.url is ' + We store url here so that we can always make party names hyperlinks + without joining to any other table. +'; + +------------------- +-- PARTY PACKAGE -- +------------------- + +-- create or replace package party +-- as +-- +-- function new ( +-- party_id in parties.party_id%TYPE default null, +-- object_type in acs_objects.object_type%TYPE +-- default 'party', +-- creation_date in acs_objects.creation_date%TYPE +-- default sysdate, +-- creation_user in acs_objects.creation_user%TYPE +-- default null, +-- creation_ip in acs_objects.creation_ip%TYPE default null, +-- email in parties.email%TYPE, +-- url in parties.url%TYPE default null, +-- context_id in acs_objects.context_id%TYPE default null +-- ) return parties.party_id%TYPE; +-- +-- procedure delete ( +-- party_id in parties.party_id%TYPE +-- ); +-- +-- function name ( +-- party_id in parties.party_id%TYPE +-- ) return varchar2; +-- +-- end party; + +-- show errors + + +-- create or replace package body party +-- function new +create function party__new (integer,varchar,timestamp,integer,varchar,varchar,varchar,integer) +returns integer as ' +declare + new__party_id alias for $1; + new__object_type alias for $2; + new__creation_date alias for $3; + new__creation_user alias for $4; + new__creation_ip alias for $5; + new__email alias for $6; + new__url alias for $7; + new__context_id alias for $8; + v_party_id parties.party_id%TYPE; +begin + v_party_id := + acs_object__new(new__party_id, new__object_type, new__creation_date, + new__creation_user, new__creation_ip, new__context_id); + + insert into parties + (party_id, email, url) + values + (v_party_id, lower(new__email), coalesce(new__url,'''')); + + return v_party_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function party__delete (integer) +returns integer as ' +declare + party_id alias for $1; +begin + PERFORM acs_object__delete(party_id); + + return 0; +end;' language 'plpgsql'; + + +-- function name +create function party__name (integer) +returns integer as ' +declare + party_id alias for $1; +begin + if party_id = -1 then + return ''The Public''; + else + return null; + end if; + +end;' language 'plpgsql'; + + + +-- show errors + +------------- +-- PERSONS -- +------------- + +create table persons ( + person_id integer not null + constraint persons_person_id_fk + references parties (party_id) + constraint persons_pk primary key, + first_names varchar(100) not null, + last_name varchar(100) not null +); + +comment on table persons is ' + Need to handle titles like Mr., Ms., Mrs., Dr., etc. and suffixes + like M.D., Ph.D., Jr., Sr., III, IV, etc. +'; + +-------------------- +-- PERSON PACKAGE -- +-------------------- + +-- create or replace package person +-- as +-- +-- function new ( +-- person_id in persons.person_id%TYPE default null, +-- object_type in acs_objects.object_type%TYPE +-- default 'person', +-- creation_date in acs_objects.creation_date%TYPE +-- default sysdate, +-- creation_user in acs_objects.creation_user%TYPE +-- default null, +-- creation_ip in acs_objects.creation_ip%TYPE default null, +-- email in parties.email%TYPE, +-- url in parties.url%TYPE default null, +-- first_names in persons.first_names%TYPE, +-- last_name in persons.last_name%TYPE, +-- context_id in acs_objects.context_id%TYPE default null +-- ) return persons.person_id%TYPE; +-- +-- procedure delete ( +-- person_id in persons.person_id%TYPE +-- ); +-- +-- function name ( +-- person_id in persons.person_id%TYPE +-- ) return varchar2; +-- +-- end person; + +-- show errors + +-- create or replace package body person +-- function new +create function person__new (integer,varchar,timestamp,integer,varchar,varchar,varchar,varchar,varchar,integer) +returns integer as ' +declare + new__person_id alias for $1; + new__object_type alias for $2; + new__creation_date alias for $3; + new__creation_user alias for $4; + new__creation_ip alias for $5; + new__email alias for $6; + new__url alias for $7; + new__first_names alias for $8; + new__last_name alias for $9; + new__context_id alias for $10; + v_person_id persons.person_id%TYPE; +begin + v_person_id := + party__new(new__person_id, new__object_type, + new__creation_date, new__creation_user, new__creation_ip, + new__email, new__url, new__context_id); + + insert into persons + (person_id, first_names, last_name) + values + (v_person_id, new__first_names, new__last_name); + + return v_person_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function person__delete (integer) +returns integer as ' +declare + delete__person_id alias for $1; +begin + delete from persons + where person_id = delete__person_id; + + PERFORM party__delete(delete__person_id); + + return 0; +end;' language 'plpgsql'; + + +-- function name +create function person__name (integer) +returns varchar as ' +declare + name__person_id alias for $1; + person_name varchar(200); +begin + select first_names || '' '' || last_name + into person_name + from persons + where person_id = name__person_id; + + return person_name; + +end;' language 'plpgsql'; + + + +-- show errors + +create table users ( + user_id integer not null + constraint users_user_id_fk + references persons (person_id) + constraint users_pk primary key, + password char(40), + salt char(40), + screen_name varchar(100) + constraint users_screen_name_un + unique, + priv_name integer default 0 not null, + priv_email integer default 5 not null, + email_verified_p boolean default 't', + email_bouncing_p boolean default 'f' not null, + no_alerts_until timestamp, + last_visit timestamp, + second_to_last_visit timestamp, + n_sessions integer default 1 not null, + password_question varchar(1000) default '' not null, + password_answer varchar(1000) default '' not null +); + +create table user_preferences ( + user_id integer constraint user_prefs_user_id_fk + references users (user_id) + constraint user_preferences_pk + primary key, + prefer_text_only_p boolean default 'f', + -- an ISO 639 language code (in lowercase) + language_preference char(2) default 'en', + dont_spam_me_p boolean default 'f', + email_type varchar(64) default '' not null +); + +create function inline_1 () +returns integer as ' +begin + + insert into acs_object_type_tables + (object_type, table_name, id_column) + values + (''user'', ''user_preferences'', ''user_id''); + return 0; +end;' language 'plpgsql'; + +select inline_1 (); + +drop function inline_1 (); + + +-- show errors + + +alter table acs_objects add + constraint acs_objects_creation_user_fk + foreign key (creation_user) references users(user_id); +alter table acs_objects add + constraint acs_objects_modifying_user_fk + foreign key (modifying_user) references users(user_id); + +comment on table users is ' + The creation_date and creation_ip columns inherited from acs_objects + indicate when and from where the user registered. How do we apply a + constraint ("email must not be null") to the parent type? +'; + +comment on column users.no_alerts_until is ' + For suppressing email alerts +'; + +comment on column users.last_visit is ' + Set when user reappears at site +'; + +comment on column users.second_to_last_visit is ' + This is what most pages query against (since last_visit will only be + a few minutes old for most pages in a session) +'; + +comment on column users.n_sessions is ' + How many times this user has visited +'; + +---------------------- +-- ACS_USER PACKAGE -- +---------------------- + +-- create or replace package acs_user +-- as +-- +-- function new ( +-- user_id in users.user_id%TYPE default null, +-- object_type in acs_objects.object_type%TYPE +-- default 'user', +-- creation_date in acs_objects.creation_date%TYPE +-- default sysdate, +-- creation_user in acs_objects.creation_user%TYPE +-- default null, +-- creation_ip in acs_objects.creation_ip%TYPE default null, +-- email in parties.email%TYPE, +-- url in parties.url%TYPE default null, +-- first_names in persons.first_names%TYPE, +-- last_name in persons.last_name%TYPE, +-- password in users.password%TYPE, +-- salt in users.salt%TYPE, +-- password_question in users.password_question%TYPE default null, +-- password_answer in users.password_answer%TYPE default null, +-- screen_name in users.screen_name%TYPE default null, +-- email_verified_p in users.email_verified_p%TYPE default 't', +-- context_id in acs_objects.context_id%TYPE default null +-- ) +-- return users.user_id%TYPE; +-- +-- function receives_alerts_p ( +-- user_id in users.user_id%TYPE +-- ) +-- return char; +-- +-- procedure approve_email ( +-- user_id in users.user_id%TYPE +-- ); +-- +-- procedure unapprove_email ( +-- user_id in users.user_id%TYPE +-- ); +-- +-- procedure delete ( +-- user_id in users.user_id%TYPE +-- ); +-- +-- end acs_user; + +-- show errors + +-- create or replace package body acs_user +-- function new +create function acs_user__new (integer,varchar,timestamp,integer,varchar,varchar,varchar,varchar,varchar,char,char,varchar,varchar,varchar,boolean,integer) +returns integer as ' +declare + new__user_id alias for $1; + new__object_type alias for $2; + new__creation_date alias for $3; + new__creation_user alias for $4; + new__creation_ip alias for $5; + new__email alias for $6; + new__url alias for $7; + new__first_names alias for $8; + new__last_name alias for $9; + new__password alias for $10; + new__salt alias for $11; + new__password_question alias for $12; + new__password_answer alias for $13; + new__screen_name alias for $14; + new__email_verified_p alias for $15; + new__context_id alias for $16; + v_user_id users.user_id%TYPE; +begin + v_user_id := + person__new(new__user_id, new__object_type, + new__creation_date, new__creation_user, new__creation_ip, + new__email, new__url, new__first_names, new__last_name, + new__context_id); + + insert into users + (user_id, password, salt, password_question, password_answer, screen_name, + email_verified_p) + values + (v_user_id, new__password, new__salt, coalesce(new__password_question,''''), + coalesce(new__password_answer,''''), new__screen_name, new__email_verified_p); + + insert into user_preferences + (user_id) + values + (v_user_id); + + return v_user_id; + +end;' language 'plpgsql'; + + +-- function receives_alerts_p +create function acs_user__receives_alerts_p (integer) +returns integer as ' +declare + receives_alerts_p__user_id alias for $1; + counter boolean; +begin + select case when count(*) = 0 then ''f'' else ''t'' end into counter + from users + where no_alerts_until >= now() + and user_id = receives_alerts_p__user_id; + + return counter; + +end;' language 'plpgsql'; + + +-- procedure approve_email +create function acs_user__approve_email (integer) +returns integer as ' +declare + approve_email__user_id alias for $1; +begin + update users + set email_verified_p = ''t'' + where user_id = approve_email__user_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure unapprove_email +create function acs_user__unapprove_email (integer) +returns integer as ' +declare + unapprove_email__user_id alias for $1; +begin + update users + set email_verified_p = ''f'' + where user_id = unapprove_email__user_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete +create function acs_user__delete (integer) +returns integer as ' +declare + delete__user_id alias for $1; +begin + delete from user_preferences + where user_id = delete__user_id; + + delete from users + where user_id = delete__user_id; + + PERFORM person__delete(delete__user_id); + + return 0; +end;' language 'plpgsql'; + + + +-- show errors Index: openacs-4/packages/acs-kernel/sql/postgresql/community-core-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/community-core-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/community-core-drop.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,27 @@ +-- +-- acs-kernel/sql/community-core-drop.sql +-- +-- DDL commands to purge the Community Core data model +-- +-- @author Michael Yoon (michael@arsdigita.com) +-- @creation-date 2000-05-18 +-- @cvs-id community-core-drop.sql,v 1.5 2000/10/24 22:26:19 bquinn Exp +-- + +-- We need to drop the circular creation_user and modifying_user +-- references before we can drop the users table. +-- +\t +alter table acs_objects drop constraint acs_objects_creation_user_fk; +alter table acs_objects drop constraint acs_objects_modifying_user_fk; + +select drop_package('acs_user'); +drop table user_preferences; +drop table users; + +select drop_package('person'); +drop table persons; + +select drop_package('party'); +drop table parties; +\t Index: openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,832 @@ +-- +-- packages/acs-kernel/sql/groups-body-create.sql +-- +-- @author rhs@mit.edu +-- @creation-date 2000-08-22 +-- @cvs-id groups-body-create.sql,v 1.1.4.1 2001/01/12 22:58:33 mbryzek Exp +-- + +-------------- +-- TRIGGERS -- +-------------- +-- a dummy trigger was defined in groups-create.sql +drop trigger membership_rels_in_tr on membership_rels; +drop function membership_rels_in_tr (); +create function membership_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 the group_member_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, ''membership_rel''); + + -- For all groups of which I am a component, insert a + -- row in the group_member_index. + for map in (select distinct group_id + from group_component_map + where component_id = v_object_id_one) loop + 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, ''membership_rel''); + end loop; + + return new; + +end;' language 'plpgsql'; + +create trigger membership_rels_in_tr after insert on membership_rels +for each row execute procedure membership_rels_in_tr (); + +-- show errors + +-- a dummy trigger was defined in groups-create.sql +drop trigger composition_rels_in_tr on composition_rels; +drop function composition_rels_in_tr(); +create 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''); + + -- 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 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 (); + +-- show errors + +create function membership_rels_del_tr () returns opaque as ' +declare + v_error text; +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; + + delete from group_element_index + where rel_id = old.rel_id; + + return new; + +end;' language 'plpgsql'; + +create trigger membership_rels_del_tr before delete on membership_rels +for each row execute procedure membership_rels_del_tr (); + +-- show errors + +-- +-- TO DO: See if this can be optimized now that the member and component +-- mapping tables have been combined +-- +create 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 + 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 + 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; + + return new; + +end;' language 'plpgsql'; + +create trigger composition_rels_del_tr before delete on composition_rels +for each row execute procedure composition_rels_del_tr (); + +-- show errors + + +-------------------- +-- PACKAGE BODIES -- +-------------------- + +-- create or replace package body composition_rel +-- function new +create function composition_rel__new (integer,varchar,integer,integer,integer,varchar) +returns integer as ' +declare + new__rel_id alias for $1; + rel_type alias for $2; + object_id_one alias for $3; + object_id_two alias for $4; + creation_user alias for $5; + creation_ip alias for $6; + v_rel_id integer; +begin + v_rel_id := acs_rel__new ( + new__rel_id, + rel_type, + object_id_one, + object_id_two, + object_id_one, + creation_user, + creation_ip + ); + + insert into composition_rels + (rel_id) + values + (v_rel_id); + + return v_rel_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function composition_rel__delete (integer) +returns integer as ' +declare + rel_id alias for $1; +begin + PERFORM acs_rel__delete(rel_id); + + return 0; +end;' language 'plpgsql'; + + +-- function check_path_exists_p +create function composition_rel__check_path_exists_p (integer,integer) +returns boolean as ' +declare + component_id alias for $1; + container_id alias for $2; + row record; +begin + if component_id = container_id then + return ''t''; + end if; + + for row in (select r.object_id_one as parent_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_two = component_id) loop + if composition_rel__check_path_exists_p(row.parent_id, container_id) = ''t'' then + return ''t''; + end if; + end loop; + + return ''f''; + +end;' language 'plpgsql'; + + +-- function check_index +create function composition_rel__check_index (integer,integer) +returns boolean as ' +declare + check_index__component_id alias for $1; + check_index__container_id alias for $2; + result boolean; + n_rows integer; + dc record; + r1 record; + r2 record; +begin + result := ''t''; + + -- Loop through all the direct containers (DC) of COMPONENT_ID + -- that are also contained by CONTAINER_ID and verify that the + -- GROUP_COMPONENT_INDEX contains the (GROUP_ID, DC.REL_ID, + -- CONTAINER_ID) triple. + for dc in (select r.rel_id, r.object_id_one as container_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_two = check_index__component_id) loop + + if composition_rel__check_path_exists_p(dc.container_id, + check_index__container_id) = ''t'' then + select case when count(*) = 0 then 0 else 1 end into n_rows + from group_component_index + where group_id = check_index__container_id + and component_id = check_index__component_id + and rel_id = dc.rel_id; + + if n_rows = 0 then + result := ''f''; + PERFORM acs_log__error(''composition_rel.check_representation'', + ''Row missing from group_component_index for ('' || + ''group_id = '' || check_index__container_id || '', '' || + ''component_id = '' || check_index__component_id || '', '' || + ''rel_id = '' || dc.rel_id || '')''); + end if; + + end if; + + end loop; + + -- Loop through all the containers of CONTAINER_ID. + for r1 in (select r.object_id_one as container_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_two = check_index__container_id + union + select check_index__container_id as container_id + from dual) loop + -- Loop through all the components of COMPONENT_ID and make a + -- recursive call. + for r2 in (select r.object_id_two as component_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_one = check_index__component_id + union + select check_index__component_id as component_id + from dual) loop + if (r1.container_id != check_index__container_id or + r2.component_id != check_index__component_id) and + composition_rel__check_index(r2.component_id, r1.container_id) = ''f'' then + result := ''f''; + end if; + end loop; + end loop; + + return result; + +end;' language 'plpgsql'; + + +-- function check_representation +create function composition_rel__check_representation (integer) +returns boolean as ' +declare + check_representation__rel_id alias for $1; + container_id groups.group_id%TYPE; + component_id groups.group_id%TYPE; + result boolean; + row record; +begin + result := ''t''; + + if acs_object__check_representation(check_representation__rel_id) = ''f'' then + result := ''f''; + end if; + + select object_id_one, object_id_two + into container_id, component_id + from acs_rels + where rel_id = check_representation__rel_id; + + -- First let''s check that the index has all the rows it should. + if composition_rel__check_index(component_id, container_id) = ''f'' then + result := ''f''; + end if; + + -- Now let''s check that the index doesn''t have any extraneous rows + -- relating to this relation. + for row in (select * + from group_component_index + where rel_id = check_representation__rel_id) loop + if composition_rel__check_path_exists_p(row.component_id, row.group_id) = ''f'' then + result := ''f''; + PERFORM acs_log__error(''composition_rel.check_representation'', + ''Extraneous row in group_component_index: '' || + ''group_id = '' || row.group_id || '', '' || + ''component_id = '' || row.component_id || '', '' || + ''rel_id = '' || row.rel_id || '', '' || + ''container_id = '' || row.container_id || ''.''); + end if; + end loop; + + return result; + +end;' language 'plpgsql'; + + + +-- show errors + + + + +-- create or replace package body membership_rel +-- function new +create function membership_rel__new (integer,varchar,integer,integer,varchar,integer,varchar) +returns integer as ' +declare + new__rel_id alias for $1; + rel_type alias for $2; + object_id_one alias for $3; + object_id_two alias for $4; + new__member_state alias for $5; + creation_user alias for $6; + creation_ip alias for $7; + v_rel_id integer; +begin + v_rel_id := acs_rel__new ( + new__rel_id, + rel_type, + object_id_one, + object_id_two, + object_id_one, + creation_user, + creation_ip + ); + + insert into membership_rels + (rel_id, member_state) + values + (v_rel_id, new__member_state); + + return v_rel_id; + +end;' language 'plpgsql'; + + +-- procedure ban +create function membership_rel__ban (integer) +returns integer as ' +declare + ban__rel_id alias for $1; +begin + update membership_rels + set member_state = ''banned'' + where rel_id = ban__rel_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure approve +create function membership_rel__approve (integer) +returns integer as ' +declare + approve__rel_id alias for $1; +begin + update membership_rels + set member_state = ''approved'' + where rel_id = approve__rel_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure reject +create function membership_rel__reject (integer) +returns integer as ' +declare + reject__rel_id alias for $1; +begin + update membership_rels + set member_state = ''rejected'' + where rel_id = reject__rel_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure unapprove +create function membership_rel__unapprove (integer) +returns integer as ' +declare + unapprove__rel_id alias for $1; +begin + update membership_rels + set member_state = ''need approval'' + where rel_id = unapprove__rel_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure deleted +create function membership_rel__deleted (integer) +returns integer as ' +declare + deleted__rel_id alias for $1; +begin + update membership_rels + set member_state = ''deleted'' + where rel_id = deleted__rel_id; + + return 0; +end;' language 'plpgsql'; + + +-- procedure delete +create function membership_rel__delete (integer) +returns integer as ' +declare + rel_id alias for $1; +begin + PERFORM acs_rel__delete(rel_id); + + return 0; +end;' language 'plpgsql'; + + +-- function check_index +create function membership_rel__check_index (integer,integer,integer) +returns boolean as ' +declare + check_index__group_id alias for $1; + check_index__member_id alias for $2; + check_index__container_id alias for $3; + result boolean; + n_rows integer; + row record; +begin + + select count(*) into n_rows + from group_member_index + where group_id = check_index__group_id + and member_id = check_index__member_id + and container_id = check_index__container_id; + + if n_rows = 0 then + result := ''f''; + PERFORM acs_log__error(''membership_rel.check_representation'', + ''Row missing from group_member_index: '' || + ''group_id = '' || check_index__group_id || '', '' || + ''member_id = '' || check_index__member_id || '', '' || + ''container_id = '' || check_index__container_id || ''.''); + end if; + + for row in (select r.object_id_one as container_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_two = check_index__group_id) loop + if membership_rel__check_index(row.container_id, check_index__member_id, check_index__container_id) = ''f'' then + result := ''f''; + end if; + end loop; + + return result; + +end;' language 'plpgsql'; + + +-- function check_representation +create function membership_rel__check_representation (integer) +returns boolean as ' +declare + check_representation__rel_id alias for $1; + group_id groups.group_id%TYPE; + member_id parties.party_id%TYPE; + result boolean; + row record; +begin + result := ''t''; + + if acs_object__check_representation(check_representation__rel_id) = ''f'' then + result := ''f''; + end if; + + select r.object_id_one, r.object_id_two + into group_id, member_id + from acs_rels r, membership_rels m + where r.rel_id = m.rel_id + and m.rel_id = check_representation__rel_id; + + if membership_rel__check_index(group_id, member_id, group_id) = ''f'' then + result := ''f''; + end if; + + for row in (select * + from group_member_index + where rel_id = check_representation__rel_id) loop + if composition_rel__check_path_exists_p(row.container_id, + row.group_id) = ''f'' then + result := ''f''; + PERFORM acs_log__error(''membership_rel.check_representation'', + ''Extra row in group_member_index: '' || + ''group_id = '' || row.group_id || '', '' || + ''member_id = '' || row.member_id || '', '' || + ''container_id = '' || row.container_id || ''.''); + end if; + end loop; + + return result; + +end;' language 'plpgsql'; + + + +-- show errors + + + +-- create or replace package body acs_group +-- function new +create function acs_group__new (integer,varchar,timestamp,integer,varchar,varchar,varchar,varchar,varchar,integer) +returns integer as ' +declare + new__group_id alias for $1; + new__object_type alias for $2; + new__creation_date alias for $3; + new__creation_user alias for $4; + new__creation_ip alias for $5; + new__email alias for $6; + new__url alias for $7; + new__group_name alias for $8; + new__join_policy alias for $9; + new__context_id alias for $10; + v_group_id groups.group_id%TYPE; + v_group_type_exists_p integer; + v_join_policy groups.join_policy%TYPE; +begin + v_group_id := + party__new(new__group_id, new__object_type, new__creation_date, + new__creation_user, new__creation_ip, new__email, + new__url, new__context_id); + + v_join_policy := new__join_policy; + + -- if join policy was not specified, select the default based on group type + if v_join_policy is null then + select count(*) into v_group_type_exists_p + from group_types + where group_type = new__object_type; + + if v_group_type_exists_p = 1 then + select default_join_policy into v_join_policy + from group_types + where group_type = new__object_type; + else + v_join_policy := ''open''; + end if; + end if; + + insert into groups + (group_id, group_name, join_policy) + values + (v_group_id, new__group_name, v_join_policy); + + -- setup the permissable relationship types for this group + insert into group_rels + (group_rel_id, group_id, rel_type) + select acs_object_id_seq.nextval, v_group_id, g.rel_type + from group_type_rels g + where g.group_type = new__object_type; + + return v_group_id; + +end;' language 'plpgsql'; + + +-- procedure delete +create function acs_group__delete (integer) +returns integer as ' +declare + delete__group_id alias for $1; + row record; +begin + + -- Delete all segments defined for this group + for row in (select segment_id + from rel_segments + where group_id = delete__group_id) loop + + PERFORM rel_segment__delete(row.segment_id); + + end loop; + + -- Delete all the relations of any type to this group + for row in (select r.rel_id, t.package_name + from acs_rels r, acs_object_types t + where r.rel_type = t.object_type + and (r.object_id_one = delete__group_id + or r.object_id_two = delete__group_id)) loop + execute ''perform '' || row.package_name || ''__delete('' || row.rel_id || '')''; + end loop; + + PERFORM party__delete(delete__group_id); + + return 0; +end;' language 'plpgsql'; + + +-- function name +create function acs_group__name (integer) +returns varchar as ' +declare + name__group_id alias for $1; + group_name varchar(200); +begin + select group_name + into group_name + from groups + where group_id = name__group_id; + + return group_name; + +end;' language 'plpgsql'; + + +-- function member_p +create function acs_group__member_p (integer) +returns boolean as ' +declare + party_id alias for $1; +begin + -- TO DO: implement this for real + return ''t''; + +end;' language 'plpgsql'; + + +-- function check_representation +create function acs_group__check_representation (integer) +returns boolean as ' +declare + group_id alias for $1; + result boolean; + c record; + m record; +begin + result := ''t''; + PERFORM acs_log__notice(''acs_group.check_representation'', + ''Running check_representation on group '' || group_id); + + if acs_object__check_representation(group_id) = ''f'' then + result := ''f''; + end if; + + for c in (select c.rel_id + from acs_rels r, composition_rels c + where r.rel_id = c.rel_id + and r.object_id_one = group_id) loop + if composition_rel__check_representation(c.rel_id) = ''f'' then + result := ''f''; + end if; + end loop; + + for m in (select m.rel_id + from acs_rels r, membership_rels m + where r.rel_id = m.rel_id + and r.object_id_one = group_id) loop + if membership_rel__check_representation(m.rel_id) = ''f'' then + result := ''f''; + end if; + end loop; + + PERFORM acs_log__notice(''acs_group.check_representation'', + ''Done running check_representation on group '' || group_id); + return result; + +end;' language 'plpgsql'; + + + +-- show errors Index: openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql 14 Mar 2001 04:39:10 -0000 1.1 @@ -0,0 +1,529 @@ +-- +-- packages/acs-kernel/sql/groups-create.sql +-- +-- @author rhs@mit.edu +-- @creation-date 2000-08-22 +-- @cvs-id groups-create.sql,v 1.16.2.3 2001/01/19 00:50:37 mbryzek Exp +-- + +---------------------------- +-- GROUP TYPES AND GROUPS -- +---------------------------- + +-- NOTE: developers should not do dml to manipulate/add/delete membership +-- or composition relations. Use the APIs (the composition_rel and +-- membership_rel pl/sql packages). In particular, NEVER UPDATE object_id_one +-- and object_id_two of acs_rels, or you'll break the denormalization (see +-- the "DENORMALIZATION" section further below). + +create table composition_rels ( + rel_id integer constraint composition_rel_rel_id_fk + references acs_rels (rel_id) + constraint composition_rel_rel_id_pk + primary key +); + +create table membership_rels ( + rel_id integer constraint membership_rel_rel_id_fk + references acs_rels (rel_id) + constraint membership_rel_rel_id_pk + primary key, + -- null means waiting for admin approval + member_state varchar(20) constraint membership_rel_mem_ck + check (member_state in ('approved', 'needs approval', + 'banned', 'rejected', 'deleted')) +); + +create function inline_0 () +returns integer as ' +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + -- + -- Group: a composite party + -- + attr_id := acs_object_type__create_type ( + ''group'', + ''Group'', + ''Groups'', + ''party'', + ''groups'', + ''group_id'', + ''acs_group'', + ''f'', + ''group_types'', + ''acs_group.name'' + ); + + attr_id := acs_attribute__create_attribute ( + ''group'', + ''group_name'', + ''string'', + ''Group name'', + ''Group names'', + null, + null, + null, + 1, + 1, + null, + ''type_specific'', + ''f'' + ); + + -- + -- Composition Relationship + -- + attr_id := acs_rel_type__create_role (''composite'', ''Composite'', ''Composites''); + attr_id := acs_rel_type__create_role (''component'', ''Component'', ''Components''); + + attr_id := acs_rel_type__create_type ( + ''composition_rel'', + ''Composition Relation'', + ''Composition Relationships'', + ''composition_rels'', + ''rel_id'', + ''composition_rel'', + ''group'', + ''composite'', + 0, + null, + ''group'', + ''component'', + 0, + null + ); + + + -- + -- Membership Relationship + -- + attr_id := acs_rel_type__create_role (''member'', ''Member'', ''Members''); + + attr_id := acs_rel_type__create_type ( + ''membership_rel'', + ''Membership Relation'', + ''Membership Relationships'', + ''membership_rels'', + ''rel_id'', + ''membership_rel'', + ''group'', + null, + 0, + null, + ''person'', + ''member'', + 0, + null + ); + + return 0; +end;' language 'plpgsql'; + +select inline_0 (); + +drop function inline_0 (); + + +-- show errors + +create table group_types ( + group_type varchar(100) not null + constraint group_types_pk primary key + constraint group_types_obj_type_fk + references acs_object_types (object_type), + approval_policy varchar(30) not null, + default_join_policy varchar(30) default 'open' not null + constraint group_types_join_policy_ck + check (default_join_policy in + ('open', 'needs approval', 'closed')) +); + +comment on table group_types is ' + This table holds additional knowledge level attributes for the + group type and its subtypes. +'; + +create table groups ( + group_id integer not null + constraint groups_group_id_fk + references parties (party_id) + constraint groups_pk primary key, + group_name varchar(100) not null, + join_policy varchar(30) default 'open' not null + constraint groups_join_policy_ck + check (join_policy in + ('open', 'needs approval', 'closed')) +); + + + +create table group_type_rels ( + group_rel_type_id integer constraint gtr_group_rel_type_id_pk primary key, + rel_type varchar(100) not null + constraint gtr_rel_type_fk + references acs_rel_types (rel_type) + on delete cascade, + group_type varchar(100) not null + constraint gtr_group_type_fk + references acs_object_types (object_type) + on delete cascade, + constraint gtr_group_rel_types_un unique (group_type, rel_type) +); + +-- rel_type references acs_rel_types. Create an index +create index group_type_rels_rel_type_idx on group_type_rels(rel_type); + +comment on table group_type_rels is ' + Stores the default relationship types available for use by groups of + a given type. We May want to generalize this table to object_types and + put it in the relationships sql file, though there is no need to do so + right now. +'; + + +create table group_rels ( + group_rel_id integer constraint group_rels_group_rel_id_pk primary key, + rel_type varchar(100) not null + constraint group_rels_rel_type_fk + references acs_rel_types (rel_type) + on delete cascade, + group_id integer not null + constraint group_rels_group_id_fk + references groups (group_id) + on delete cascade, + constraint group_rels_group_rel_type_un unique (group_id, rel_type) +); + +-- rel_type references acs_rel_types. Create an index +create index group_rels_rel_type_idx on group_rels(rel_type); + +comment on table group_rels is ' + Stores the relationship types available for use by each group. Only + relationship types in this table are offered for adding + relations. Note that there is no restriction that says groups can + only have relationship types specified for their group type. The +
group_type_rels
table just stores defaults for groups
+ of a new type.
+';
+
+
+------------------------------------------
+-- DENORMALIZATION: group_element_index --
+------------------------------------------
+
+-- group_element_index is an internal mapping table maintained by the
+-- parties system for optimizaiton of the views in the "VIEWS" section
+-- further below.
+
+-- Instead of writing a complicated trigger to keep this map up to
+-- date when people edit membership or composition relationships, I
+-- think I'm going to make it illegal to mutate membership or
+-- composition relationships, or at least the object_id_one and
+-- object_id_two columns, since I don't know that it makes sense
+-- anyways. Also, by making this constraint we can probably do some
+-- nifty optimizaitons at some point in the future.
+
+-- This means, you can't edit a membership or composition relation.
+-- Instead, you have to delete the relation and recreate it. By doing this,
+-- we only have "on insert" and "on delete" triggers and avoid maintaining
+-- the more complex "on update" trigger"
+
+-- oumi@arsdigita.com - Jan 04, 2001 -
+-- Combined group_member_index and group_element_index into one table. This
+-- allows for simpler queries about party aggregation, especially for
+-- relational segments (see rel-segments-create.sql).
+
+create table group_element_index (
+ group_id integer not null
+ constraint group_element_index_grp_id_fk
+ references groups (group_id),
+ element_id integer not null
+ constraint group_element_index_elem_id_fk
+ references parties (party_id),
+ rel_id integer not null
+ constraint group_element_index_rel_id_fk
+ references acs_rels (rel_id),
+ container_id integer not null
+ constraint group_element_index_cont_id_fk
+ references groups (group_id),
+ rel_type varchar(100) not null
+ constraint group_elem_index_rel_type_fk
+ references acs_rel_types (rel_type),
+ ancestor_rel_type varchar(100) not null
+ constraint grp_el_idx_ancstr_rel_type_ck
+ check (ancestor_rel_type in ('composition_rel','membership_rel')),
+ constraint group_element_index_pk
+ primary key (element_id, group_id, rel_id)
+);
+
+create index group_elem_idx_group_idx on group_element_index (group_id);
+create index group_elem_idx_element_idx on group_element_index (element_id);
+create index group_elem_idx_rel_id_idx on group_element_index (rel_id);
+create index group_elem_idx_container_idx on group_element_index (container_id);
+create index group_elem_idx_rel_type_idx on group_element_index (rel_type);
+
+comment on table group_element_index is '
+ This table is for internal use by the parties system. It as an auxiliary
+ table, a denormalization of data, that is used to improve performance.
+ Do not query on this table or insert into it. Query on group_element_map
+ instead. And insert by using the API''s for membership_rel, composition_rel,
+ or some sub-type of those relationship types.
+';
+
+
+-----------
+-- VIEWS --
+-----------
+
+create view group_element_map
+as select group_id, element_id, rel_id, container_id,
+ rel_type, ancestor_rel_type
+ from group_element_index;
+
+create view group_component_map
+as select group_id, element_id as component_id, rel_id, container_id, rel_type
+ from group_element_map
+ where ancestor_rel_type='composition_rel';
+
+create view group_member_map
+as select group_id, element_id as member_id, rel_id, container_id, rel_type
+ from group_element_map
+ where ancestor_rel_type='membership_rel';
+
+create view group_approved_member_map
+as select gm.group_id, gm.member_id, gm.rel_id, gm.container_id, gm.rel_type
+ from group_member_map gm, membership_rels mr
+ where gm.rel_id = mr.rel_id
+ and mr.member_state = 'approved';
+
+create view group_distinct_member_map
+as select distinct group_id, member_id
+ from group_approved_member_map;
+
+-- some more views, like party_memeber_map and party_approved_member_map,
+-- are created in rel-segments-create.sql
+
+-- Just in case someone is still querying the group_component_index and
+-- group_member_index directly, lets make them views.
+create view group_component_index as select * from group_component_map;
+create view group_member_index as select * from group_member_map;
+
+
+---------------
+-- FUNCTIONS --
+---------------
+-- drop function group_contains_p (integer, integer, integer);
+create function group_contains_p (integer, integer, integer)
+returns boolean as '
+declare
+ group_contains_p__group_id alias for $1;
+ group_contains_p__component_id alias for $2;
+ group_contains_p__rel_id alias for $3;
+ map record;
+begin
+ if group_contains_p__group_id = group_contains_p__component_id then
+ return ''t'';
+ else
+ if group_contains_p__rel_id is null then
+ for map in (select *
+ from group_component_map
+ where component_id = group_contains_p__component_id
+ and group_id = container_id) loop
+ if group_contains_p(group_contains_p__group_id, map.group_id) = ''t'' then
+ return ''t'';
+ end if;
+ end loop;
+ else
+ for map in (select *
+ from group_component_map
+ where component_id = group_contains_p__component_id
+ and rel_id = group_contains_p__rel_id
+ and group_id = container_id) loop
+ if group_contains_p(group_contains_p__group_id, map.group_id) = ''t'' then
+ return ''t'';
+ end if;
+ end loop;
+ end if;
+ return ''f'';
+ end if;
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
+
+------------------------
+-- TEMPORARY TRIGGERS --
+------------------------
+
+-- These triggers are used to prevent people from defining membership
+-- or composition relations until the groups-triggers-create file is
+-- sourced. That file will replace these triggers with triggers
+-- that actually do useful work
+
+create function membership_rels_in_tr () returns opaque as '
+declare
+begin
+ raise EXCEPTION ''%: %'', -20000,''Insert to membership rels not yet supported'';
+
+ return new;
+
+end;' language 'plpgsql';
+
+create trigger membership_rels_in_tr after insert on membership_rels
+for each row execute procedure membership_rels_in_tr ();
+
+-- show errors
+
+
+create function composition_rels_in_tr () returns opaque as '
+declare
+begin
+ raise EXCEPTION ''%: %'', -20000,''Insert to membership rels not yet supported'';
+
+ 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();
+
+-- show errors
+
+
+---------------------------------------------
+-- POPULATE DATA FOR PERMISSABLE REL TYPES --
+---------------------------------------------
+
+-- define standard types for groups of type 'group'
+insert into group_type_rels
+(group_rel_type_id, rel_type, group_type)
+values
+(acs_object_id_seq.nextval, 'membership_rel', 'group');
+
+insert into group_type_rels
+(group_rel_type_id, rel_type, group_type)
+values
+(acs_object_id_seq.nextval, 'composition_rel', 'group');
+
+
+--------------
+-- PACKAGES --
+--------------
+
+-- create or replace package composition_rel
+-- as
+--
+-- function new (
+-- rel_id in composition_rels.rel_id%TYPE default null,
+-- rel_type in acs_rels.rel_type%TYPE default 'composition_rel',
+-- object_id_one in acs_rels.object_id_one%TYPE,
+-- object_id_two in acs_rels.object_id_two%TYPE,
+-- creation_user in acs_objects.creation_user%TYPE default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null
+-- ) return composition_rels.rel_id%TYPE;
+--
+-- procedure delete (
+-- rel_id in composition_rels.rel_id%TYPE
+-- );
+--
+-- function check_path_exists_p (
+-- component_id in groups.group_id%TYPE,
+-- container_id in groups.group_id%TYPE
+-- ) return char;
+--
+-- function check_representation (
+-- rel_id in composition_rels.rel_id%TYPE
+-- ) return char;
+--
+-- end composition_rel;
+
+-- show errors
+
+
+-- create or replace package membership_rel
+-- as
+--
+-- function new (
+-- rel_id in membership_rels.rel_id%TYPE default null,
+-- rel_type in acs_rels.rel_type%TYPE default 'membership_rel',
+-- object_id_one in acs_rels.object_id_one%TYPE,
+-- object_id_two in acs_rels.object_id_two%TYPE,
+-- member_state in membership_rels.member_state%TYPE default 'approved',
+-- creation_user in acs_objects.creation_user%TYPE default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null
+-- ) return membership_rels.rel_id%TYPE;
+--
+-- procedure ban (
+-- rel_id in membership_rels.rel_id%TYPE
+-- );
+--
+-- procedure approve (
+-- rel_id in membership_rels.rel_id%TYPE
+-- );
+--
+-- procedure reject (
+-- rel_id in membership_rels.rel_id%TYPE
+-- );
+--
+-- procedure unapprove (
+-- rel_id in membership_rels.rel_id%TYPE
+-- );
+--
+-- procedure deleted (
+-- rel_id in membership_rels.rel_id%TYPE
+-- );
+--
+-- procedure delete (
+-- rel_id in membership_rels.rel_id%TYPE
+-- );
+--
+-- function check_representation (
+-- rel_id in membership_rels.rel_id%TYPE
+-- ) return char;
+--
+-- end membership_rel;
+
+-- show errors
+
+
+-- create or replace package acs_group
+-- is
+-- function new (
+-- group_id in groups.group_id%TYPE default null,
+-- object_type in acs_objects.object_type%TYPE
+-- default 'group',
+-- creation_date in acs_objects.creation_date%TYPE
+-- default sysdate,
+-- creation_user in acs_objects.creation_user%TYPE
+-- default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null,
+-- email in parties.email%TYPE default null,
+-- url in parties.url%TYPE default null,
+-- group_name in groups.group_name%TYPE,
+-- join_policy in groups.join_policy%TYPE default null,
+-- context_id in acs_objects.context_id%TYPE default null
+-- ) return groups.group_id%TYPE;
+--
+-- procedure delete (
+-- group_id in groups.group_id%TYPE
+-- );
+--
+-- function name (
+-- group_id in groups.group_id%TYPE
+-- ) return varchar2;
+--
+-- function member_p (
+-- party_id in parties.party_id%TYPE
+-- ) return char;
+--
+-- function check_representation (
+-- group_id in groups.group_id%TYPE
+-- ) return char;
+--
+-- end acs_group;
+
+-- show errors
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/groups-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/groups-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/groups-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,27 @@
+-
+-- packages/acs-kernel/sql/groups-drop.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-08-22
+-- @cvs-id groups-drop.sql,v 1.5.2.1 2001/01/12 23:01:01 mbryzek Exp
+--
+\t
+select drop_package('acs_group');
+drop function group_contains_p(integer,integer,integer);
+drop view group_distinct_member_map;
+drop view group_approved_member_map;
+drop view group_member_index;
+drop view group_component_index;
+drop view group_member_map;
+drop view group_component_map;
+drop view group_element_map;
+drop table group_element_index;
+drop table group_type_rels;
+drop table group_rels;
+drop table groups;
+select drop_package('composition_rel');
+select drop_package('membership_rel');
+drop table composition_rels;
+drop table membership_rels;
+drop table group_types;
+\t
Index: openacs-4/packages/acs-kernel/sql/postgresql/journal-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/journal-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/journal-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,158 @@
+-- Data model to keep a journal of all actions on objects.
+--
+--
+-- @author Lars Pind (lars@pinds.com)
+-- @creation-date 2000-22-18
+-- @cvs-id journal-create.sql,v 1.7.2.1 2000/12/08 00:38:24 yon Exp
+--
+-- Copyright (C) 1999-2000 ArsDigita Corporation
+--
+-- This is free software distributed under the terms of the GNU Public
+-- License. Full text of the license is available from the GNU Project:
+-- http://www.fsf.org/copyleft/gpl.html
+
+
+create function inline_0 ()
+returns integer as '
+begin
+ PERFORM acs_object_type__create_type (
+ ''journal_entry'',
+ ''Journal Entry'',
+ ''Journal Entries'',
+ ''acs_object'',
+ ''journal_entries'',
+ ''journal_id'',
+ ''journal_entry'',
+ ''f'',
+ null,
+ null
+ );
+
+ -- XXX fill in all the attributes in later.
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
+
+create table journal_entries (
+ journal_id integer constraint journal_entries_journal_id_fk
+ references acs_objects (object_id)
+ constraint journal_entries_pk
+ primary key,
+ object_id integer
+ constraint journal_entries_object_fk
+ references acs_objects on delete cascade,
+ action varchar(100) default '' not null,
+ action_pretty text default '' not null,
+ msg text default '' not null
+);
+
+create index journal_entries_object_idx on journal_entries (object_id);
+
+comment on table journal_entries is '
+ Keeps track of actions performed on objects, e.g. banning a user,
+ starting or finishing a workflow task, etc.
+';
+
+
+-- create or replace package journal_entry
+-- as
+--
+-- function new (
+-- journal_id in journal_entries.journal_id%TYPE default null,
+-- object_id in journal_entries.object_id%TYPE,
+-- action in journal_entries.action%TYPE,
+-- action_pretty in journal_entries.action_pretty%TYPE default null,
+-- creation_date in acs_objects.creation_date%TYPE default sysdate,
+-- creation_user in acs_objects.creation_user%TYPE default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null,
+-- msg in journal_entries.msg%TYPE default null
+-- ) return journal_entries.journal_id%TYPE;
+--
+-- procedure delete(
+-- journal_id in journal_entries.journal_id%TYPE
+-- );
+--
+-- procedure delete_for_object(
+-- object_id in acs_objects.object_id%TYPE
+-- );
+--
+-- end journal_entry;
+
+-- show errors
+
+-- create or replace package body journal_entry
+-- function new
+create function journal_entry__new (integer,integer,varchar,varchar,timestamp,integer,varchar,varchar)
+returns integer as '
+declare
+ new__journal_id alias for $1;
+ new__object_id alias for $2;
+ new__action alias for $3;
+ new__action_pretty alias for $4;
+ new__creation_date alias for $5;
+ new__creation_user alias for $6;
+ new__creation_ip alias for $7;
+ new__msg alias for $8;
+ v_journal_id journal_entries.journal_id%TYPE;
+begin
+ v_journal_id := acs_object__new (
+ new__journal_id,
+ ''journal_entry'',
+ new__creation_date,
+ new__creation_user,
+ new__creation_ip,
+ new__object_id
+ );
+
+ insert into journal_entries (
+ journal_id, object_id, action, action_pretty, msg
+ ) values (
+ v_journal_id, new__object_id, coalesce(new__action,''''),
+ coalesce(new__action_pretty,''''), coalesce(new__msg,'''')
+ );
+
+ return v_journal_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure delete
+create function journal_entry__delete (integer)
+returns integer as '
+declare
+ delete__journal_id alias for $1;
+begin
+ delete from journal_entries where journal_id = delete__journal_id;
+ PERFORM acs_object__delete(delete__journal_id);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- procedure delete_for_object
+create function journal_entry__delete_for_object (integer)
+returns integer as '
+declare
+ delete_for_object__object_id alias for $1;
+ journal_rec record;
+begin
+ for journal_rec in select journal_id
+ from journal_entries
+ where object_id = delete_for_object__object_id
+ LOOP
+ PERFORM journal_entry__delete(journal_rec.journal_id);
+ end loop;
+
+ return 0;
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/journal-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/journal-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/journal-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,24 @@
+--
+-- acs-kernel/sql/acs-objects-drop.sql
+--
+-- DDL commands to purge the ACS Objects data model
+--
+-- @author Lars Pind (lars@pinds.com)
+-- @creation-date 2000-22-18
+-- @cvs-id journal-drop.sql,v 1.5 2000/10/24 22:26:20 bquinn Exp
+--
+
+\t
+create function inline_0 () returns integer as '
+begin
+ PERFORM acs_object_type__drop_type(
+ ''journal_entry'', ''f''
+ );
+ return null;
+end;' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0 ();
+select drop_package('journal_entry');
+\t
+drop table journal_entries;
Index: openacs-4/packages/acs-kernel/sql/postgresql/load-data1.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/load-data1.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/load-data1.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,34 @@
+
+
+
+insert into acs_object_types (object_type,supertype)
+ values
+ ('acs_object', null);
+insert into acs_object_types (object_type,supertype)
+ values
+ ('relationship', 'acs_object');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('party', 'acs_object');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('person', 'party');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('user', 'person');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('group', 'party');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('membership_rel', 'acs_object');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('composition_rel', 'acs_object');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('journal_entry', 'acs_object');
+insert into acs_object_types (object_type,supertype)
+ values
+ ('site_node', 'acs_object');
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/postgresql.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/postgresql.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/postgresql.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,373 @@
+create function instr(varchar,char,integer,integer) returns integer as '
+declare
+ str alias for $1;
+ pat alias for $2;
+ dir alias for $3;
+ cnt alias for $4;
+ v_len integer;
+ v_i integer;
+ v_c char;
+ v_cnt integer;
+ v_inc integer;
+begin
+ v_len := length(str);
+ v_cnt := 0;
+
+ if dir < 0 then
+ v_inc := \-1;
+ v_i := v_len;
+ else
+ v_inc := 1;
+ v_i := 1;
+ end if;
+
+ while v_i > 0 and v_i <= v_len LOOP
+ v_c := substr(str,v_i,1);
+ if v_c::char = pat::char then
+ v_cnt := v_cnt + 1;
+ if v_cnt = cnt then
+ return v_i;
+ end if;
+ end if;
+ v_i := v_i + v_inc;
+ end loop;
+
+ return 0;
+
+end;' language 'plpgsql';
+
+
+create function instr(varchar,char,integer) returns integer as '
+declare
+ str alias for $1;
+ pat alias for $2;
+ dir alias for $3;
+begin
+ return instr(str,pat,dir,1);
+end;' language 'plpgsql';
+
+
+create function get_func_drop_command (varchar) returns varchar as '
+declare
+ fname alias for $1;
+ nargs integer default 0;
+ v_pos integer;
+ v_funcdef text;
+ v_args varchar;
+ v_one_arg varchar;
+ v_one_type varchar;
+ v_nargs integer;
+begin
+ v_funcdef := ''drop function '' || fname || ''('';
+
+ select proargtypes, pronargs
+ into v_args, v_nargs
+ from pg_proc
+ where proname = fname::name;
+
+ v_pos := position('' '' in v_args);
+
+ while nargs < v_nargs loop
+ nargs := nargs + 1;
+ if nargs = v_nargs then
+ v_one_arg := v_args;
+ v_args := '''';
+ else
+ v_one_arg := substr(v_args, 1, v_pos \- 1);
+ v_args := substr(v_args, v_pos + 1);
+ v_pos := position('' '' in v_args);
+ end if;
+ select case when nargs = 1
+ then typname
+ else '','' || typname
+ end into v_one_type
+ from pg_type
+ where oid = v_one_arg;
+ v_funcdef := v_funcdef || v_one_type;
+ end loop;
+ v_funcdef := v_funcdef || '')'';
+
+ return v_funcdef;
+
+end;' language 'plpgsql';
+
+create function drop_package (varchar) returns varchar as '
+declare
+ package_name alias for $1;
+ v_rec record;
+ v_drop_cmd varchar;
+ v_pkg_name varchar;
+begin
+ raise NOTICE ''DROP PACKAGE: %'', package_name;
+ v_pkg_name := package_name || ''\\\\_\\\\_'' || ''%'';
+
+ for v_rec in select proname
+ from pg_proc
+ where proname like v_pkg_name
+ order by proname
+ LOOP
+ raise NOTICE ''DROPPING FUNCTION: %'', v_rec.proname;
+ v_drop_cmd := get_func_drop_command (v_rec.proname);
+ EXECUTE v_drop_cmd;
+ end loop;
+
+ if NOT FOUND then
+ raise EXCEPTION ''PACKAGE: % NOT FOUND'', package_name;
+ else
+ raise NOTICE ''PACKAGE: %: DROPPED'', package_name;
+ end if;
+
+ return null;
+
+end;' language 'plpgsql';
+
+
+-- tree query support, m-vgID method.
+
+CREATE TABLE tree_encodings (
+ deci int primary key,
+ code char(1)
+);
+
+create index tree_encode_idx on tree_encodings(code);
+
+
+copy tree_encodings from stdin using delimiters '/' ;
+0/0
+1/1
+2/2
+3/3
+4/4
+5/5
+6/6
+7/7
+8/8
+9/9
+10/:
+11/;
+12/A
+13/B
+14/C
+15/D
+16/E
+17/F
+18/G
+19/H
+20/I
+21/J
+22/K
+23/L
+24/M
+25/N
+26/O
+27/P
+28/Q
+29/R
+30/S
+31/T
+32/U
+33/V
+34/W
+35/X
+36/Y
+37/Z
+38/a
+39/b
+40/c
+41/d
+42/e
+43/f
+44/g
+45/h
+46/i
+47/j
+48/k
+49/l
+50/m
+51/n
+52/o
+53/p
+54/q
+55/r
+56/s
+57/t
+58/u
+59/v
+60/w
+61/x
+62/y
+63/z
+64/�
+65/�
+66/�
+67/�
+68/�
+69/�
+70/�
+71/�
+72/�
+73/�
+74/�
+75/�
+76/�
+77/�
+78/�
+79/�
+80/�
+81/�
+82/�
+83/�
+84/�
+85/�
+86/�
+87/�
+88/�
+89/�
+90/�
+91/�
+92/�
+93/�
+94/�
+95/�
+96/�
+97/�
+98/�
+99/�
+100/�
+101/�
+102/�
+103/�
+104/�
+105/�
+106/�
+107/�
+108/�
+109/�
+110/�
+111/�
+112/�
+113/�
+114/�
+115/�
+116/�
+117/�
+118/�
+119/�
+120/�
+121/�
+122/�
+123/�
+124/�
+125/�
+126/�
+127/�
+128/�
+129/�
+130/�
+131/�
+132/�
+133/�
+134/�
+135/�
+136/�
+137/�
+138/�
+139/�
+140/�
+141/�
+142/�
+143/�
+144/�
+145/�
+146/�
+147/�
+148/�
+149/�
+150/�
+151/�
+152/�
+153/�
+154/�
+155/�
+156/�
+157/�
+158/�
+\.
+
+create function tree_default_encoding_base() returns integer as '
+begin
+ return 159;
+end;' language 'plpgsql';
+
+create function tree_next_key(varchar) returns varchar as '
+declare
+ skey alias for $1;
+ pos integer;
+ stop boolean default ''f'';
+ carry boolean default ''t'';
+ nkey varchar default '''';
+ base integer;
+ ch char(1);
+begin
+ base := tree_default_encoding_base();
+
+ if skey is null then
+
+ return ''00'';
+
+ else
+ pos := length(skey);
+ LOOP
+ ch := substr(skey,pos,1);
+ if carry = ''t'' then
+ select code::varchar || nkey,
+ case when code = ''0''
+ then ''t''
+ else ''f''
+ end into nkey, carry
+ from tree_encodings
+ where deci = (select (deci + 1) % base
+ from tree_encodings
+ where code = ch);
+ else
+ nkey := ch::varchar || nkey;
+ end if;
+ pos := pos - 1;
+ select case when substr(skey,pos - 1,1) = ''/''
+ then ''t''
+ else ''f''
+ end into stop;
+
+ exit when stop = ''t'';
+
+ END LOOP;
+ if carry = ''t'' then
+ nkey := ''0'' || nkey;
+ end if;
+ end if;
+
+ select code::varchar || nkey into nkey
+ from tree_encodings
+ where deci = length(nkey) - 1;
+
+ return nkey;
+
+end;' language 'plpgsql';
+
+
+create function tree_level(varchar) returns integer as '
+declare
+ inkey alias for $1;
+ cnt integer default 0;
+begin
+ for i in 1..length(inkey) LOOP
+ if substr(inkey,i,1) = ''/'' then
+ cnt := cnt + 1;
+ end if;
+ end LOOP;
+
+ return cnt;
+
+end;' language 'plpgsql';
+
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/rel-constraints-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/rel-constraints-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/rel-constraints-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,661 @@
+--
+-- /packages/acs-kernel/sql/rel-constraints-create.sql
+--
+-- Add support for relational constraints based on relational segmentation.
+--
+-- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- @creation-date 2000-11-22
+-- @cvs-id rel-constraints-create.sql,v 1.1.4.8 2001/01/23 17:03:58 oumi Exp
+
+-- Copyright (C) 1999-2000 ArsDigita Corporation
+-- This is free software distributed under the terms of the GNU Public
+-- License. Full text of the license is available from the GNU Project:
+-- http://www.fsf.org/copyleft/gpl.html
+
+-- WARNING!
+-- Relational constraints is a new and experimental concept. The API may
+-- change in the future, particularly the functions marked "EXPERIMENTAL".
+--
+
+create function inline_0 ()
+returns integer as '
+begin
+ PERFORM acs_object_type__create_type (
+ ''rel_constraint'',
+ ''Relational Constraint'',
+ ''Relational Constraints'',
+ ''acs_object'',
+ ''rel_constraints'',
+ ''constraint_id'',
+ ''rel_constraint'',
+ ''f'',
+ null,
+ null
+ );
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
+
+
+create table rel_constraints (
+ constraint_id integer
+ constraint rel_constraints_pk
+ primary key
+ constraint rc_constraint_id_fk
+ references acs_objects(object_id),
+ constraint_name varchar(100) not null,
+ rel_segment integer not null
+ constraint rc_rel_segment_fk
+ references rel_segments (segment_id),
+ rel_side char(3) default 'two' not null
+ constraint rc_rel_side_ck
+ check (rel_side in
+ ('one', 'two')),
+ required_rel_segment integer not null
+ constraint rc_required_rel_segment
+ references rel_segments (segment_id),
+ constraint rel_constraints_uq
+ unique (rel_segment, rel_side, required_rel_segment)
+);
+
+-- required_rel_segment has a foreign key reference - create an index
+create index rel_constraint_req_rel_seg_idx on rel_constraints(required_rel_segment);
+
+
+comment on table rel_constraints is '
+ Defines relational constraints. The relational constraints system is
+ intended to support applications in modelling and applying
+ constraint rules on inter-party relatinships based on relational
+ party segmentation.
+';
+
+
+comment on column rel_constraints.constraint_name is '
+ The user-defined name of this constraint.
+';
+
+comment on column rel_constraints.rel_segment is '
+ The segment for which the constraint is defined.
+';
+
+comment on column rel_constraints.rel_side is '
+ The side of the relation the constraint applies to.
+';
+
+comment on column rel_constraints.required_rel_segment is '
+ The segment in which elements must be in to satisfy the constraint.
+';
+
+
+
+-----------
+-- VIEWS --
+-----------
+
+-- View rel_constraints_violated_one
+--
+-- pseudo sql:
+--
+-- select all the side 'one' constraints
+-- from the constraints and the associated relations of rel_segment
+-- where the relation's container_id (i.e., object_id_one) is not in the
+-- relational segment required_rel_segment.
+/*
+create view rel_constraints_violated_one as
+select constrained_rels.*
+from (select rel_constraints.constraint_id, rel_constraints.constraint_name,
+ r.rel_id, r.container_id, r.party_id, r.rel_type,
+ rel_constraints.rel_segment,
+ rel_constraints.rel_side,
+ rel_constraints.required_rel_segment
+ from rel_constraints, rel_segment_party_map r
+ where rel_constraints.rel_side = 'one'
+ and rel_constraints.rel_segment = r.segment_id
+ ) constrained_rels,
+ rel_segment_party_map rspm
+where rspm.segment_id(+) = constrained_rels.required_rel_segment
+ and rspm.party_id(+) = constrained_rels.container_id
+ and rspm.party_id is null;
+*/
+
+create view rel_constraints_violated_one as
+select constrained_rels.*
+from (select rel_constraints.constraint_id, rel_constraints.constraint_name,
+ r.rel_id, r.container_id, r.party_id, r.rel_type,
+ rel_constraints.rel_segment,
+ rel_constraints.rel_side,
+ rel_constraints.required_rel_segment
+ from rel_constraints, rel_segment_party_map r
+ where rel_constraints.rel_side = 'one'
+ and rel_constraints.rel_segment = r.segment_id
+ ) constrained_rels left outer join rel_segment_party_map rspm
+ on (rspm.segment_id = constrained_rels.required_rel_segment and
+ rspm.party_id = constrained_rels.container_id)
+where rspm.party_id is null;
+
+
+-- Originally, we tried this view. It was slow. The one above is much
+-- less slow. It moves the "not exists" query to an outer join, checking
+-- for null rows in the outer join table. This turns out to be much faster
+-- than "not exists".
+--
+-- create or replace view rel_constraints_violated_one as
+-- select rel_constraints.constraint_id, rel_constraints.constraint_name,
+-- r.rel_id, r.container_id, r.party_id, r.rel_type,
+-- rel_constraints.rel_segment,
+-- rel_constraints.rel_side,
+-- rel_constraints.required_rel_segment
+-- from rel_constraints, rel_segment_party_map r
+-- where rel_constraints.rel_side = 'one'
+-- and rel_constraints.rel_segment = r.segment_id
+-- and not exists (
+-- select 1 from rel_segment_party_map rspm
+-- where rspm.segment_id = rel_constraints.required_rel_segment
+-- and rspm.party_id = r.container_id
+-- );
+
+
+-- View rel_constraints_violated_two
+--
+-- pseudo sql:
+--
+-- select all the side 'two' constraints
+-- from the constraints and the associated relations of rel_segment
+-- where the relation's party_id (i.e., object_id_two) is not in the
+-- relational segment required_rel_segment.
+/*
+create view rel_constraints_violated_two as
+select constrained_rels.*
+from (select rel_constraints.constraint_id, rel_constraints.constraint_name,
+ r.rel_id, r.container_id, r.party_id, r.rel_type,
+ rel_constraints.rel_segment,
+ rel_constraints.rel_side,
+ rel_constraints.required_rel_segment
+ from rel_constraints, rel_segment_party_map r
+ where rel_constraints.rel_side = 'two'
+ and rel_constraints.rel_segment = r.segment_id
+ ) constrained_rels,
+ rel_segment_party_map rspm
+where rspm.segment_id(+) = constrained_rels.required_rel_segment
+ and rspm.party_id(+) = constrained_rels.party_id
+ and rspm.party_id is null;
+*/
+
+create view rel_constraints_violated_two as
+select constrained_rels.*
+from (select rel_constraints.constraint_id, rel_constraints.constraint_name,
+ r.rel_id, r.container_id, r.party_id, r.rel_type,
+ rel_constraints.rel_segment,
+ rel_constraints.rel_side,
+ rel_constraints.required_rel_segment
+ from rel_constraints, rel_segment_party_map r
+ where rel_constraints.rel_side = 'two'
+ and rel_constraints.rel_segment = r.segment_id
+ ) constrained_rels left outer join rel_segment_party_map rspm
+ on (rspm.segment_id = constrained_rels.required_rel_segment and
+ rspm.party_id = constrained_rels.party_id)
+where rspm.party_id is null;
+
+-- Originally, we tried this view. It was slow. The one above is much
+-- less slow. It moves the "not exists" query to an outer join, checking
+-- for null rows in the outer join table. This turns out to be much faster
+-- than "not exists".
+--
+-- create or replace view rel_constraints_violated_two as
+-- select rel_constraints.constraint_id, rel_constraints.constraint_name,
+-- r.rel_id, r.container_id, r.party_id, r.rel_type,
+-- rel_constraints.rel_segment,
+-- rel_constraints.rel_side,
+-- rel_constraints.required_rel_segment
+-- from rel_constraints, rel_segment_party_map r
+-- where rel_constraints.rel_side = 'two'
+-- and rel_constraints.rel_segment = r.segment_id
+-- and not exists (
+-- select 1 from rel_segment_party_map rspm
+-- where rspm.segment_id = rel_constraints.required_rel_segment
+-- and rspm.party_id = r.party_id
+-- );
+
+
+
+-- View: rc_all_constraints
+--
+-- Question: Given group :group_id and rel_type :rel_type . . .
+--
+-- What segments must a party be in
+-- if the party were to be on side :rel_side of a relation of
+-- type :rel_type to group :group_id ?
+--
+-- Answer: select required_rel_segment
+-- from rc_all_constraints
+-- where group_id = :group_id
+-- and rel_type = :rel_type
+-- and rel_side = :rel_side
+--
+-- Notes: we take special care not to get identity rows, where group_id and
+-- rel_type are equivalent to segment_id. This can happen if there are some
+-- funky constraints in the system, such as membership to Arsdigita requires
+-- user_profile to Arsdigita. Then you could get rows from the
+-- rc_all_constraints view saying that:
+-- user_profile to Arsdigita
+-- requires being in the segment of Arsdigita Users.
+--
+-- This happens because user_profile is a type of memebrship, and there's a
+-- constraint saying that membership to Arsdigita requires being in the
+-- Arsdigita Users segment. We eliminate such rows from the rc_all_constraints
+-- view with the "not (...)" clause below.
+--
+create view rc_all_constraints as
+select group_rel_types.group_id,
+ group_rel_types.rel_type,
+ rel_constraints.rel_segment,
+ rel_constraints.rel_side,
+ required_rel_segment
+ from rel_constraints,
+ rel_segment_group_rel_type_map group_rel_types,
+ rel_segments req_seg
+ where rel_constraints.rel_segment = group_rel_types.segment_id
+ and rel_constraints.required_rel_segment = req_seg.segment_id
+ and not (req_seg.group_id = group_rel_types.group_id and
+ req_seg.rel_type = group_rel_types.rel_type);
+
+
+create view rc_all_distinct_constraints as
+select distinct
+ group_id, rel_type, rel_segment, rel_side, required_rel_segment
+from rc_all_constraints;
+
+
+-- THIS VIEW IS FOR COMPATIBILITY WITH EXISTING CODE
+-- New code should use rc_all_constraints instead!
+--
+-- View: rc_required_rel_segments
+--
+-- Question: Given group :group_id and rel_type :rel_type . . .
+--
+-- What segments must a party be in
+-- if the party were to be belong to group :group_id
+-- through a relation of type :rel_type ?
+--
+-- Answer: select required_rel_segment
+-- from rc_required_rel_segments
+-- where group_id = :group_id
+-- and rel_type = :rel_type
+--
+
+create view rc_required_rel_segments as
+select distinct group_id, rel_type, required_rel_segment
+from rc_all_constraints
+where rel_side = 'two';
+
+
+-- View: rc_parties_in_required_segs
+--
+-- Question: Given group :group_id and rel_type :rel_type . . .
+--
+-- What parties are "allowed" to be in group :group_id
+-- through a relation of type :rel_type ? By "allowed",
+-- we mean that no relational constraints would be violated.
+--
+-- Answer: select party_id, acs_object.name(party_id)
+-- from parties_in_rc_required_rel_segments
+-- where group_id = :group_id
+-- and rel_type = :rel_type
+--
+
+-- create view rc_parties_in_required_segs as
+-- select parties_in_required_segs.group_id,
+-- parties_in_required_segs.rel_type,
+-- parties_in_required_segs.party_id
+-- from
+-- (select required_segs.group_id,
+-- required_segs.rel_type,
+-- seg_parties.party_id,
+-- count(*) as num_matching_segs
+-- from rc_required_rel_segments required_segs,
+-- rel_segment_party_map seg_parties
+-- where required_segs.required_rel_segment = seg_parties.segment_id
+-- group by required_segs.group_id,
+-- required_segs.rel_type,
+-- seg_parties.party_id) parties_in_required_segs,
+-- (select group_id, rel_type, count(*) as total
+-- from rc_required_rel_segments
+-- group by group_id, rel_type) total_num_required_segs
+-- where
+-- parties_in_required_segs.group_id = total_num_required_segs.group_id
+-- and parties_in_required_segs.rel_type = total_num_required_segs.rel_type
+-- and parties_in_required_segs.num_matching_segs = total_num_required_segs.total
+-- UNION ALL
+-- select group_rel_type_combos.group_id,
+-- group_rel_type_combos.rel_type,
+-- parties.party_id
+-- from rc_required_rel_segments,
+-- (select groups.group_id, comp_or_member_rel_types.rel_type
+-- from groups,
+-- (select object_type as rel_type from acs_object_types
+-- start with object_type = 'membership_rel'
+-- or object_type = 'composition_rel'
+-- -- connect by supertype = prior object_type) comp_or_member_rel_types
+-- ) group_rel_type_combos,
+-- parties
+-- where rc_required_rel_segments.group_id(+) = group_rel_type_combos.group_id
+-- and rc_required_rel_segments.rel_type(+) = group_rel_type_combos.rel_type
+-- and rc_required_rel_segments.group_id is null;
+
+
+
+
+create view rc_parties_in_required_segs as
+select parties_in_required_segs.group_id,
+ parties_in_required_segs.rel_type,
+ parties_in_required_segs.party_id
+from
+ (select required_segs.group_id,
+ required_segs.rel_type,
+ seg_parties.party_id,
+ count(*) as num_matching_segs
+ from rc_required_rel_segments required_segs,
+ rel_segment_party_map seg_parties
+ where required_segs.required_rel_segment = seg_parties.segment_id
+ group by required_segs.group_id,
+ required_segs.rel_type,
+ seg_parties.party_id) parties_in_required_segs,
+ (select group_id, rel_type, count(*) as total
+ from rc_required_rel_segments
+ group by group_id, rel_type) total_num_required_segs
+where
+ parties_in_required_segs.group_id = total_num_required_segs.group_id
+ and parties_in_required_segs.rel_type = total_num_required_segs.rel_type
+ and parties_in_required_segs.num_matching_segs = total_num_required_segs.total
+UNION ALL
+select group_rel_type_combos.group_id,
+ group_rel_type_combos.rel_type,
+ parties.party_id
+from (rc_required_rel_segments right outer join
+ (select groups.group_id, comp_or_member_rel_types.rel_type
+ from groups,
+ (select object_type as rel_type
+ from acs_object_types
+ where tree_sortkey like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = 'composition_rel')
+ or tree_sortkey like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = 'membership_rel')) comp_or_member_rel_types
+ ) group_rel_type_combos on (rc_required_rel_segments.group_id = group_rel_type_combos.group_id and rc_required_rel_segments.rel_type = group_rel_type_combos.rel_type)), parties
+where rc_required_rel_segments.group_id is null;
+
+
+-- View: rc_valid_rel_types
+--
+-- Question: What types of membership or composition are "valid"
+-- for group :group_id ? A membership or composition
+-- type R is "valid" when no relational constraints would
+-- be violated if a party were to belong to group :group_id
+-- through a rel of type R.
+--
+-- Answer: select rel_type
+-- from rc_valid_rel_types
+-- where group_id = :group_id
+--
+--
+
+-- create view rc_valid_rel_types as
+-- select side_one_constraints.group_id,
+-- side_one_constraints.rel_type
+-- from (select required_segs.group_id,
+-- required_segs.rel_type,
+-- count(*) as num_satisfied
+-- from rc_all_constraints required_segs,
+-- rel_segment_party_map map
+-- where required_segs.rel_side = 'one'
+-- and required_segs.required_rel_segment = map.segment_id
+-- and required_segs.group_id = map.party_id
+-- group by required_segs.group_id,
+-- required_segs.rel_type) side_one_constraints,
+-- (select group_id, rel_type, count(*) as total
+-- from rc_all_constraints
+-- where rel_side = 'one'
+-- group by group_id, rel_type) total_side_one_constraints
+-- where side_one_constraints.group_id = total_side_one_constraints.group_id
+-- and side_one_constraints.rel_type = total_side_one_constraints.rel_type
+-- and side_one_constraints.num_satisfied = total_side_one_constraints.total
+-- UNION ALL
+-- select group_rel_type_combos.group_id,
+-- group_rel_type_combos.rel_type
+-- from (select * from rc_all_constraints where rel_side='one') rc_all_constraints,
+-- (select groups.group_id, comp_or_member_rel_types.rel_type
+-- from groups,
+-- (select object_type as rel_type from acs_object_types
+-- start with object_type = 'membership_rel'
+-- or object_type = 'composition_rel'
+-- connect by supertype = prior object_type) comp_or_member_rel_types
+-- ) group_rel_type_combos
+-- where rc_all_constraints.group_id(+) = group_rel_type_combos.group_id
+-- and rc_all_constraints.rel_type(+) = group_rel_type_combos.rel_type
+-- and rc_all_constraints.group_id is null;
+
+
+
+create view rc_valid_rel_types as
+select side_one_constraints.group_id,
+ side_one_constraints.rel_type
+ from (select required_segs.group_id,
+ required_segs.rel_type,
+ count(*) as num_satisfied
+ from rc_all_constraints required_segs,
+ rel_segment_party_map map
+ where required_segs.rel_side = 'one'
+ and required_segs.required_rel_segment = map.segment_id
+ and required_segs.group_id = map.party_id
+ group by required_segs.group_id,
+ required_segs.rel_type) side_one_constraints,
+ (select group_id, rel_type, count(*) as total
+ from rc_all_constraints
+ where rel_side = 'one'
+ group by group_id, rel_type) total_side_one_constraints
+ where side_one_constraints.group_id = total_side_one_constraints.group_id
+ and side_one_constraints.rel_type = total_side_one_constraints.rel_type
+ and side_one_constraints.num_satisfied = total_side_one_constraints.total
+UNION ALL
+select group_rel_type_combos.group_id,
+ group_rel_type_combos.rel_type
+from (select * from rc_all_constraints where rel_side='one') rc_all_constraints
+ right outer join
+ (select groups.group_id, comp_or_member_rel_types.rel_type
+ from groups,
+ (select object_type as rel_type
+ from acs_object_types
+ where tree_sortkey like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = 'composition_rel')
+ or tree_sortkey like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = 'membership_rel')) comp_or_member_rel_types
+ ) group_rel_type_combos on
+ (rc_all_constraints.group_id = group_rel_type_combos.group_id and
+ rc_all_constraints.rel_type = group_rel_type_combos.rel_type)
+where rc_all_constraints.group_id is null;
+
+-- View: rc_violations_by_removing_rel
+--
+-- Question: Given relation :rel_id
+--
+-- If we were to remove the relation specified by rel_id,
+-- what constraints would be violated and by what parties?
+--
+-- Answer: select r.rel_id, r.constraint_id, r.constraint_name
+-- acs_object_type.pretty_name(r.rel_type) as rel_type_pretty_name,
+-- acs_object.name(r.object_id_one) as object_id_one_name,
+-- acs_object.name(r.object_id_two) as object_id_two_name
+-- from rc_violations_by_removing_rel r
+-- where r.rel_id = :rel_id
+--
+
+create view rc_violations_by_removing_rel as
+select r.rel_type as viol_rel_type, r.rel_id as viol_rel_id,
+ r.object_id_one as viol_object_id_one, r.object_id_two as viol_object_id_two,
+ s.rel_id,
+ cons.constraint_id, cons.constraint_name,
+ map.segment_id, map.party_id, map.group_id, map.container_id, map.ancestor_rel_type
+ from acs_rels r, rel_segment_party_map map, rel_constraints cons,
+ (select s.segment_id, r.rel_id, r.object_id_two
+ from rel_segments s, acs_rels r
+ where r.object_id_one = s.group_id
+ and r.rel_type = s.rel_type) s
+ where map.party_id = r.object_id_two
+ and map.rel_id = r.rel_id
+ and r.object_id_two = s.object_id_two
+ and cons.rel_segment = map.segment_id
+ and cons.required_rel_segment = s.segment_id;
+
+
+-- View: rc_segment_required_seg_map
+--
+-- Question: Given a relational segment :rel_segment . . .
+--
+-- What are all the segments in the system that a party has to
+-- be in if the party were to be on side :rel_side of a relation
+-- in segement :rel_segment?
+--
+-- We want not only the direct required_segments (which we could
+-- get from the rel_constraints table directly), but also the
+-- indirect ones (i.e., the segments that are required by the
+-- required segments, and so on).
+--
+-- Answer: select required_rel_segment
+-- from rc_segment_required_seg_map
+-- where rel_segment = :rel_segment
+-- and rel_side = :rel_side
+--
+--
+create view rc_segment_required_seg_map as
+select rc.rel_segment, rc.rel_side, rc_required.required_rel_segment
+from rel_constraints rc, rel_constraints rc_required
+where rc.rel_segment in (
+ select rel_segment
+ from rel_constraints
+ start with rel_segment = rc_required.rel_segment
+ connect by required_rel_segment = prior rel_segment
+ and prior rel_side = 'two'
+ );
+
+-- View: rc_segment_dependency_levels
+--
+-- This view is designed to determine what order of segments is safe
+-- to use when adding a party to multiple segments.
+--
+-- Question: Given a table or view called segments_I_want_to_be_in,
+-- which segments can I add a party to first, without violating
+-- any relational constraints?
+--
+-- Answer: select segment_id
+-- from segments_I_want_to_be_in s,
+-- rc_segment_dependency_levels dl
+-- where s.segment_id = dl.segment_id(+)
+-- order by nvl(dl.dependency_level, 0)
+--
+-- Note: dependency_level = 1 is the minimum dependency level.
+-- dependency_level = N means that you cannot add a party to the
+-- segment until you first add the party to some
+-- segment of dependency_level N-1 (this view doesn't
+-- tell you which segment -- you can get that info
+-- from rel_constraints table or other views.
+--
+-- Another Note: not all segemnts in rel_segemnts are returned by this view.
+-- This view only returns segments S that have at least one rel_constraints row
+-- where rel_segment = S. Segments that have no constraints defined on them
+-- can be said to have dependency_level=0, hence the outer join and nvl in the
+-- example query above (see "Answer:"). I could have embeded that logic into
+-- this view, but that would unnecessarily degrade performance.
+--
+create view rc_segment_dependency_levels as
+ select rel_segment as segment_id,
+ max(tree_level) as dependency_level
+ from (select rel_segment, level as tree_level
+ from rel_constraints
+ connect by required_rel_segment = prior rel_segment
+ and prior rel_side = 'two')
+ group by rel_segment;
+
+--------------
+-- PACKAGES --
+--------------
+
+
+-- create or replace package rel_constraint
+-- as
+--
+-- function new (
+-- --/** Creates a new relational constraint
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- --*/
+-- constraint_id in rel_constraints.constraint_id%TYPE default null,
+-- constraint_type in acs_objects.object_type%TYPE default 'rel_constraint',
+-- constraint_name in rel_constraints.constraint_name%TYPE,
+-- rel_segment in rel_constraints.rel_segment%TYPE,
+-- rel_side in rel_constraints.rel_side%TYPE default 'two',
+-- required_rel_segment in rel_constraints.required_rel_segment%TYPE,
+-- context_id in acs_objects.context_id%TYPE default null,
+-- creation_user in acs_objects.creation_user%TYPE default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null
+-- ) return rel_constraints.constraint_id%TYPE;
+--
+-- procedure delete (
+-- constraint_id in rel_constraints.constraint_id%TYPE
+-- );
+--
+-- function get_constraint_id (
+-- --/** Returns the constraint_id associated with the specified
+-- -- rel_segment and required_rel_segment for the specified site.
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- --*/
+-- rel_segment in rel_constraints.rel_segment%TYPE,
+-- rel_side in rel_constraints.rel_side%TYPE default 'two',
+-- required_rel_segment in rel_constraints.required_rel_segment%TYPE
+-- ) return rel_constraints.constraint_id%TYPE;
+--
+-- function violation (
+-- --/** Checks to see if there a relational constraint is violated
+-- -- by the precense of the specified relation. If not, returns
+-- -- null. If so, returns an appropriate error string.
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- -- @param rel_id The relation for which we want to find
+-- -- any violations
+-- --*/
+-- rel_id in acs_rels.rel_id%TYPE
+-- ) return varchar;
+--
+--
+-- function violation_if_removed (
+-- --/** Checks to see if removing the specified relation would violate
+-- -- a relational constraint. If not, returns null. If so, returns
+-- -- an appropriate error string.
+-- --
+-- -- @author Michael Bryzek (mbryzek@arsdigita.com)
+-- -- @creation-date 1/2001
+-- --
+-- -- @param rel_id The relation that we are planning to remove
+-- --*/
+-- rel_id in acs_rels.rel_id%TYPE
+-- ) return varchar;
+--
+-- end;
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/rel-constraints-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/rel-constraints-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/rel-constraints-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,23 @@
+--
+-- /packages/acs-kernel/sql/rel-constraints-drop.sql
+--
+-- @author Oumi Mehrotra
+-- @creation-date 2000-11-22
+-- @cvs-id rel-constraints-drop.sql,v 1.1.4.1 2001/01/12 22:58:51 mbryzek Exp
+\t
+create function inline_0 () returns integer as '
+begin
+ PERFORM acs_rel_type__drop_type(''rel_constraint'');
+ return null;
+end;' language 'plpgsql';
+select inline_0 ();
+drop function inline_0 ();
+
+drop view rel_constraints_violated_one;
+drop view rel_constraints_violated_two;
+drop view rc_required_rel_segments;
+drop view rc_parties_in_required_segs;
+drop view rc_violations_by_removing_rel;
+drop table rel_constraints;
+select drop_package('rel_constraint');
+\t
Index: openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-body-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-body-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-body-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,158 @@
+--
+-- packages/acs-kernel/sql/rel-segments-create.sql
+--
+-- @author Oumi Mehrotra oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id rel-segments-body-create.sql,v 1.1.4.1 2001/01/12 22:58:33 mbryzek Exp
+
+-- Copyright (C) 1999-2000 ArsDigita Corporation
+-- This is free software distributed under the terms of the GNU Public
+-- License. Full text of the license is available from the GNU Project:
+-- http://www.fsf.org/copyleft/gpl.html
+
+------------------
+-- PACKAGE BODY --
+------------------
+
+-- create or replace package body rel_segment
+-- function new
+create function rel_segment__new (integer,varchar,timestamp,integer,varchar,varchar,varchar,varchar,integer,varchar,integer)
+returns integer as '
+declare
+ new__segment_id alias for $1;
+ object_type alias for $2;
+ creation_date alias for $3;
+ creation_user alias for $4;
+ creation_ip alias for $5;
+ email alias for $6;
+ url alias for $7;
+ new__segment_name alias for $8;
+ new__group_id alias for $9;
+ new__rel_type alias for $10;
+ context_id alias for $11;
+ v_segment_id rel_segments.segment_id%TYPE;
+begin
+ v_segment_id :=
+ party__new(new__segment_id, object_type, creation_date, creation_user,
+ creation_ip, email, url, context_id);
+
+ insert into rel_segments
+ (segment_id, segment_name, group_id, rel_type)
+ values
+ (v_segment_id, new__segment_name, new__group_id, new__rel_type);
+
+ return v_segment_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure delete
+create function rel_segment__delete (integer)
+returns integer as '
+declare
+ delete__segment_id alias for $1;
+ row record;
+begin
+
+ -- remove all constraints on this segment
+ for row in (select constraint_id
+ from rel_constraints
+ where rel_segment = delete__segment_id) loop
+
+ PERFORM rel_constraint__delete(row.constraint_id);
+
+ end loop;
+
+ PERFORM party__delete(delete__segment_id);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function get
+create function rel_segment__get (integer,varchar)
+returns integer as '
+declare
+ get__group_id alias for $1;
+ get__rel_type alias for $2;
+ v_segment_id rel_segments.segment_id%TYPE;
+begin
+ select min(segment_id) into v_segment_id
+ from rel_segments
+ where group_id = get__group_id
+ and rel_type = get__rel_type;
+
+ return v_segment_id;
+
+end;' language 'plpgsql';
+
+
+-- function get_or_new
+create function rel_segment__get_or_new (integer,varchar,varchar)
+returns integer as '
+declare
+ get_or_new__group_id alias for $1;
+ get_or_new__rel_type alias for $2;
+ segment_name alias for $3;
+ v_segment_id rel_segments.segment_id%TYPE;
+ v_segment_name rel_segments.segment_name%TYPE;
+begin
+
+ v_segment_id := rel_segment__get(get_or_new__group_id,get_or_new__rel_type);
+
+ if v_segment_id is null then
+
+ if v_segment_name is not null then
+ v_segment_name := segment_name;
+ else
+ select groups.group_name || '' - '' || acs_object_types.pretty_name ||
+ '' segment''
+ into v_segment_name
+ from groups, acs_object_types
+ where groups.group_id = get_or_new__group_id
+ and acs_object_types.object_type = get_or_new__rel_type;
+
+ end if;
+
+ v_segment_id := rel_segment__new (
+ null,
+ ''rel_segment'',
+ now(),
+ null,
+ null,
+ null,
+ null,
+ v_segment_name,
+ get_or_new__group_id,
+ get_or_new__rel_type,
+ get_or_new__group_id
+ );
+
+ end if;
+
+ return v_segment_id;
+
+
+end;' language 'plpgsql';
+
+
+-- function name
+create function rel_segment__name (integer)
+returns varchar as '
+declare
+ name__segment_id alias for $1;
+ segment_name varchar(200);
+begin
+ select segment_name
+ into segment_name
+ from rel_segments
+ where segment_id = name__segment_id;
+
+ return segment_name;
+
+end;' language 'plpgsql';
+
+
+
+-- show errors
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,327 @@
+--
+-- packages/acs-kernel/sql/rel-segments-create.sql
+--
+-- @author Oumi Mehrotra oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id rel-segments-create.sql,v 1.1.4.3 2001/01/16 18:54:05 oumi Exp
+
+-- Copyright (C) 1999-2000 ArsDigita Corporation
+-- This is free software distributed under the terms of the GNU Public
+-- License. Full text of the license is available from the GNU Project:
+-- http://www.fsf.org/copyleft/gpl.html
+
+-- WARNING!
+-- Relational segments is a new and experimental concept. The API may
+-- change in the future, particularly the functions marked "EXPERIMENTAL".
+--
+
+create function inline_0 ()
+returns integer as '
+begin
+ --
+ -- Relational Segment: a dynamically derived set of parties, defined
+ -- in terms of a particular type of membership or
+ -- composition to a particular group.
+ --
+ PERFORM acs_object_type__create_type (
+ ''rel_segment'',
+ ''Relational Party Segment'',
+ ''Relational Party Segments'',
+ ''party'',
+ ''rel_segments'',
+ ''segment_id'',
+ ''rel_segment'',
+ ''f'',
+ ''rel_segment'',
+ ''rel_segment.name''
+ );
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
+
+
+-- Note that we do not use on delete cascade on the group_id or
+-- rel_type column because rel_segments are acs_objects. On delete
+-- cascade only deletes the corresponding row in this table, not all
+-- the rows up the type hierarchy. Thus, rel segments must be deleted
+-- using rel_segment.delete before dropping a relationship type.
+
+create table rel_segments (
+ segment_id integer not null
+ constraint rel_segments_segment_id_fk
+ references parties (party_id)
+ constraint rel_segments_pk primary key,
+ segment_name varchar(230) not null,
+ group_id integer not null
+ constraint rel_segments_group_id_fk
+ references groups (group_id),
+ rel_type varchar(100) not null
+ constraint rel_segments_rel_type_fk
+ references acs_rel_types (rel_type),
+ constraint rel_segments_grp_rel_type_uq unique(group_id, rel_type)
+);
+
+-- rel_type has a foreign key reference - create an index
+create index rel_segments_rel_type_idx on rel_segments(rel_type);
+
+comment on table rel_segments is '
+ Defines relational segments. Each relational segment is a pair of
+ group_id
/ rel_type
, or, in english, the
+ parties that have a relation of type rel_type to group_id.
+';
+
+comment on column rel_segments.segment_name is '
+ The user-entered name of the relational segment.
+';
+
+comment on column rel_segments.group_id is '
+ The group for which this segment was created.
+';
+
+comment on column rel_segments.rel_type is '
+ The relationship type used to define elements in this segment.
+';
+
+
+-- create pl/sql package rel_segment
+
+-- create or replace package rel_segment
+-- is
+-- function new (
+-- --/** Creates a new relational segment
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- --*/
+-- segment_id in rel_segments.segment_id%TYPE default null,
+-- object_type in acs_objects.object_type%TYPE
+-- default 'rel_segment',
+-- creation_date in acs_objects.creation_date%TYPE
+-- default sysdate,
+-- creation_user in acs_objects.creation_user%TYPE
+-- default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null,
+-- email in parties.email%TYPE default null,
+-- url in parties.url%TYPE default null,
+-- segment_name in rel_segments.segment_name%TYPE,
+-- group_id in rel_segments.group_id%TYPE,
+-- rel_type in rel_segments.rel_type%TYPE,
+-- context_id in acs_objects.context_id%TYPE default null
+-- ) return rel_segments.segment_id%TYPE;
+--
+-- procedure delete (
+-- --/** Deletes a relational segment
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- --*/
+-- segment_id in rel_segments.segment_id%TYPE
+-- );
+--
+-- function name (
+-- segment_id in rel_segments.segment_id%TYPE
+-- ) return rel_segments.segment_name%TYPE;
+--
+-- function get (
+-- --/** EXPERIMENTAL / UNSTABLE -- use at your own risk
+-- -- Get the id of a segment given a group_id and rel_type.
+-- -- This depends on the uniqueness of group_id,rel_type. We
+-- -- might remove the unique constraint in the future, in which
+-- -- case we would also probably remove this function.
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- --*/
+--
+-- group_id in rel_segments.group_id%TYPE,
+-- rel_type in rel_segments.rel_type%TYPE
+-- ) return rel_segments.segment_id%TYPE;
+--
+-- function get_or_new (
+-- --/** EXPERIMENTAL / UNSTABLE -- use at your own risk
+-- --
+-- -- This function simplifies the use of segments a little by letting
+-- -- you not have to worry about creating and initializing segments.
+-- -- If the segment you're interested in exists, this function
+-- -- returns its segment_id.
+-- -- If the segment you're interested in doesn't exist, this function
+-- -- does a pretty minimal amount of initialization for the segment
+-- -- and returns a new segment_id.
+-- --
+-- -- @author Oumi Mehrotra (oumi@arsdigita.com)
+-- -- @creation-date 12/2000
+-- --
+-- --*/
+-- group_id in rel_segments.group_id%TYPE,
+-- rel_type in rel_segments.rel_type%TYPE,
+-- segment_name in rel_segments.segment_name%TYPE
+-- default null
+-- ) return rel_segments.segment_id%TYPE;
+--
+-- end rel_segment;
+
+-- show errors
+
+
+-----------
+-- Views --
+-----------
+
+-- create view rel_segment_party_map
+-- as select rs.segment_id, gem.element_id as party_id, gem.rel_id, gem.rel_type,
+-- gem.group_id, gem.container_id, gem.ancestor_rel_type
+-- from rel_segments rs,
+-- group_element_map gem
+-- where gem.group_id = rs.group_id
+-- and rs.rel_type in (select object_type
+-- from acs_object_types
+-- start with object_type = gem.rel_type
+-- connect by prior supertype = object_type);
+
+create view rel_segment_party_map
+as select rs.segment_id, gem.element_id as party_id, gem.rel_id, gem.rel_type,
+ gem.group_id, gem.container_id, gem.ancestor_rel_type
+ from rel_segments rs,
+ group_element_map gem
+ where gem.group_id = rs.group_id
+ and rs.rel_type in (select object_type
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = gem.rel_type
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%'));
+
+create view rel_segment_distinct_party_map
+as select distinct segment_id, party_id, ancestor_rel_type
+ from rel_segment_party_map;
+
+create view rel_segment_member_map
+as select segment_id, party_id as member_id, rel_id, rel_type,
+ group_id, container_id
+ from rel_segment_party_map
+ where ancestor_rel_type = 'membership_rel';
+
+
+-- Need to find out what this optimizer hint does? DCW, 2001-03-13.
+-- create view rel_seg_approved_member_map
+-- as select /*+ ordered */
+-- rs.segment_id, gem.element_id as member_id, gem.rel_id, gem.rel_type,
+-- gem.group_id, gem.container_id
+-- from membership_rels mr, group_element_map gem, rel_segments rs
+-- where rs.group_id = gem.group_id
+-- and rs.rel_type in (select object_type
+-- from acs_object_types
+-- start with object_type = gem.rel_type
+-- connect by prior supertype = object_type)
+-- and mr.rel_id = gem.rel_id and mr.member_state = 'approved';
+
+
+create view rel_seg_approved_member_map
+as select rs.segment_id, gem.element_id as member_id, gem.rel_id,
+ gem.rel_type, gem.group_id, gem.container_id
+ from membership_rels mr, group_element_map gem, rel_segments rs
+ where rs.group_id = gem.group_id
+ and rs.rel_type in (select object_type
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = gem.rel_type
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%'))
+ and mr.rel_id = gem.rel_id and mr.member_state = 'approved';
+
+create view rel_seg_distinct_member_map
+as select distinct segment_id, member_id
+ from rel_seg_approved_member_map;
+
+
+-- party_member_map can be used to expand any party into its members.
+-- Every party is considered to be a member of itself.
+
+-- By the way, aren't the party_member_map and party_approved_member_map
+-- views equivalent?? (TO DO: RESOLVE THIS QUESTION)
+
+create view party_member_map
+as select segment_id as party_id, member_id
+ from rel_seg_distinct_member_map
+ union
+ select group_id as party_id, member_id
+ from group_distinct_member_map
+ union
+ select party_id, party_id as member_id
+ from parties;
+
+create view party_approved_member_map
+as select distinct segment_id as party_id, member_id
+ from rel_seg_approved_member_map
+ union
+ select distinct group_id as party_id, member_id
+ from group_approved_member_map
+ union
+ select party_id, party_id as member_id
+ from parties;
+
+-- party_element_map tells us all the parties that "belong to" a party,
+-- whether through somet type of membership, composition, or identity.
+
+create view party_element_map
+as select distinct group_id as party_id, element_id
+ from group_element_map
+ union
+ select distinct segment_id as party_id, party_id as element_id
+ from rel_segment_party_map
+ union
+ select party_id, party_id as element_id
+ from parties;
+
+
+-- View: rel_segment_group_rel_type_map
+--
+-- Result Set: the set of triples (:segment_id, :group_id, :rel_type) such that
+--
+-- IF a party were to be in :group_id
+-- through a relation of type :rel_type,
+-- THEN the party would necessarily be in segment :segemnt_id.
+--
+--
+-- create view rel_segment_group_rel_type_map as
+-- select s.segment_id,
+-- gcm.component_id as group_id,
+-- acs_rel_types.rel_type as rel_type
+-- from rel_segments s,
+-- (select group_id, component_id
+-- from group_component_map
+-- UNION ALL
+-- select group_id, group_id as component_id
+-- from groups) gcm,
+-- acs_rel_types
+-- where s.group_id = gcm.group_id
+-- and s.rel_type in (select object_type from acs_object_types
+-- start with object_type = acs_rel_types.rel_type
+-- connect by prior supertype = object_type);
+
+create view rel_segment_group_rel_type_map as
+select s.segment_id,
+ gcm.component_id as group_id,
+ acs_rel_types.rel_type as rel_type
+from rel_segments s,
+ (select group_id, component_id
+ from group_component_map
+ UNION ALL
+ select group_id, group_id as component_id
+ from groups) gcm,
+ acs_rel_types
+where s.group_id = gcm.group_id
+ and s.rel_type in (select object_type
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = acs_rel_types.rel_type
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%'));
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,32 @@
+--
+-- packages/acs-kernel/sql/rel-segments-drop.sql
+--
+-- @author oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id rel-segments-drop.sql,v 1.1.4.1 2001/01/12 22:58:51 mbryzek Exp
+\t
+create function inline_0 ()
+declare
+ r record;
+begin
+ for r in (select segment_id from rel_segments) loop
+ PERFORM rel_segment__delete(r.segment_id);
+ end loop;
+
+ PERFORM acs_object_type__drop_type(''rel_segment'');
+ return null;
+end;' language 'plpgsql';
+select inline_0 ();
+
+drop view party_element_map;
+drop view party_approved_member_map;
+drop view party_member_map;
+drop view rel_seg_distinct_member_map;
+drop view rel_seg_approved_member_map;
+drop view rel_segment_member_map;
+drop view rel_segment_distinct_party_map;
+drop view rel_segment_party_map;
+drop index rel_segments_rel_type_idx;
+drop table rel_segments;
+select drop_package('rel_segment');
+\t
Index: openacs-4/packages/acs-kernel/sql/postgresql/security-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/security-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/security-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,51 @@
+--
+-- /packages/acs-kernel/sql/security-create.sql
+--
+-- ACS Security data model
+--
+-- @author Jon Salz (jsalz@mit.edu)
+-- @author Kai Wu (kai@arsdigita.com)
+-- @author Richard Li (richardl@arsdigita.com)
+--
+-- @creation-date 2000/02/02
+-- @cvs-id security-create.sql,v 1.16.2.4 2001/01/12 22:58:16 mbryzek Exp
+
+create table sec_session_properties (
+ session_id integer
+ constraint sec_session_prop_session_id_nn
+ not null,
+ module varchar(50)
+ constraint sec_session_prop_module_nn
+ not null,
+ property_name varchar(50)
+ constraint sec_session_prop_prop_name_nn
+ not null,
+ property_value text default '' not null,
+ -- transmitted only across secure connections?
+ secure_p boolean,
+ last_hit integer
+ constraint sec_session_date_nn
+ not null,
+ primary key(session_id, module, property_name)
+);
+
+create index sec_property_names on sec_session_properties(property_name);
+
+create table secret_tokens (
+ token_id integer
+ constraint secret_tokens_token_id_pk primary key,
+ token char(40),
+ timestamp timestamp
+);
+
+create sequence t_sec_security_token_id_seq cache 100;
+create view sec_security_token_id_seq as
+select nextval('t_sec_security_token_id_seq') as nextval;
+
+-- Due to the nature of DDL, the increment by 100 parameter needs to
+-- be hard-coded into the sec_allocate_session procedure. Don't change
+-- the increment here without changing the procedure!
+
+create sequence t_sec_id_seq cache 100 increment 100;
+create view sec_id_seq as
+select nextval('t_sec_id_seq') as nextval;
Index: openacs-4/packages/acs-kernel/sql/postgresql/security-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/security-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/security-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,17 @@
+--
+-- /packages/acs-kernel/sql/security-drop.sql
+--
+-- DDL statements to purge the Security data model
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+-- @creation-date 2000-07-27
+-- @cvs-id security-drop.sql,v 1.9.2.1 2000/12/07 15:02:15 richardl Exp
+--
+
+drop view sec_id_seq;
+drop sequence t_sec_id_seq;
+drop view sec_security_token_id_seq;
+drop sequence t_sec_security_token_id_seq;
+drop table sec_session_properties;
+drop index sec_sessions_by_server;
+drop table secret_tokens;
Index: openacs-4/packages/acs-kernel/sql/postgresql/site-nodes-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/site-nodes-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/site-nodes-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,284 @@
+--
+-- packages/acs-kernel/sql/site-nodes-create.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-09-05
+-- @cvs-id site-nodes-create.sql,v 1.6.2.2 2001/01/12 22:53:32 dennis Exp
+--
+
+create function inline_0 ()
+returns integer as '
+declare
+ dummy integer;
+begin
+ PERFORM acs_object_type__create_type (
+ ''site_node'',
+ ''Site Node'',
+ ''Site Nodes'',
+ ''acs_object'',
+ ''site_nodes'',
+ ''node_id'',
+ ''site_node'',
+ ''f'',
+ null,
+ null
+ );
+
+ return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+
+drop function inline_0 ();
+
+
+-- show errors
+
+-- This table allows urls to be mapped to a node_ids.
+
+create table site_nodes (
+ node_id integer constraint site_nodes_node_id_fk
+ references acs_objects (object_id)
+ constraint site_nodes_node_id_pk
+ primary key,
+ parent_id integer constraint site_nodes_parent_id_fk
+ references site_nodes (node_id),
+ name varchar(100)
+ constraint site_nodes_name_ck
+ check (name not like '%/%'),
+ constraint site_nodes_un
+ unique (parent_id, name),
+ -- Is it legal to create a child node?
+ directory_p boolean not null,
+ -- Should urls that are logical children of this node be
+ -- mapped to this node?
+ pattern_p boolean default 'f' not null,
+ object_id integer constraint site_nodes_object_id_fk
+ references acs_objects (object_id)
+);
+
+create index site_nodes_object_id_idx on site_nodes (object_id);
+
+-- create or replace package site_node
+-- as
+--
+-- -- Create a new site node. If you set directory_p to be 'f' then you
+-- -- cannot create nodes that have this node as their parent.
+--
+-- function new (
+-- node_id in site_nodes.node_id%TYPE default null,
+-- parent_id in site_nodes.node_id%TYPE default null,
+-- name in site_nodes.name%TYPE,
+-- object_id in site_nodes.object_id%TYPE default null,
+-- directory_p in site_nodes.directory_p%TYPE,
+-- pattern_p in site_nodes.pattern_p%TYPE default 'f',
+-- creation_user in acs_objects.creation_user%TYPE default null,
+-- creation_ip in acs_objects.creation_ip%TYPE default null
+-- ) return site_nodes.node_id%TYPE;
+--
+-- -- Delete a site node.
+--
+-- procedure delete (
+-- node_id in site_nodes.node_id%TYPE
+-- );
+--
+-- -- Return the node_id of a url. If the url begins with '/' then the
+-- -- parent_id must be null. This will raise the no_data_found
+-- -- exception if there is no mathing node in the site_nodes table.
+-- -- This will match directories even if no trailing slash is included
+-- -- in the url.
+--
+-- function node_id (
+-- url in varchar2,
+-- parent_id in site_nodes.node_id%TYPE default null
+-- ) return site_nodes.node_id%TYPE;
+--
+-- -- Return the url of a node_id.
+--
+-- function url (
+-- node_id in site_nodes.node_id%TYPE
+-- ) return varchar2;
+--
+-- end;
+
+-- show errors
+
+-- create or replace package body site_node
+-- function new
+create function site_node__new (integer,integer,varchar,integer,boolean,boolean,integer,varchar)
+returns integer as '
+declare
+ new__node_id alias for $1;
+ new__parent_id alias for $2;
+ new__name alias for $3;
+ new__object_id alias for $4;
+ new__directory_p alias for $5;
+ new__pattern_p alias for $6;
+ new__creation_user alias for $7;
+ new__creation_ip alias for $8;
+ v_node_id site_nodes.node_id%TYPE;
+ v_directory_p site_nodes.directory_p%TYPE;
+begin
+ if new__parent_id is not null then
+ select directory_p into v_directory_p
+ from site_nodes
+ where node_id = new__parent_id;
+
+ if v_directory_p = ''f'' then
+ raise EXCEPTION ''%: %'',
+ -20000,
+ ''Node '' || new__parent_id || '' is not a directory'';
+ end if;
+ end if;
+
+ v_node_id := acs_object__new (
+ new__node_id,
+ ''site_node'',
+ now(),
+ new__creation_user,
+ new__creation_ip,
+ null
+ );
+
+ insert into site_nodes
+ (node_id, parent_id, name, object_id, directory_p, pattern_p)
+ values
+ (v_node_id, new__parent_id, new__name, new__object_id,
+ new__directory_p, new__pattern_p);
+
+ return v_node_id;
+
+end;' language 'plpgsql';
+
+
+-- procedure delete
+create function site_node__delete (integer)
+returns integer as '
+declare
+ delete__node_id alias for $1;
+begin
+ delete from site_nodes
+ where node_id = delete__node_id;
+
+ PERFORM acs_object__delete(delete__node_id);
+
+ return 0;
+end;' language 'plpgsql';
+
+
+-- function find_pattern
+create function site_node__find_pattern (integer)
+returns integer as '
+declare
+ find_pattern__node_id alias for $1;
+ v_pattern_p site_nodes.pattern_p%TYPE;
+ v_parent_id site_nodes.node_id%TYPE;
+begin
+ if node_id is null then
+-- raise no_data_found;
+ raise exception ''NO DATA FOUND'';
+ end if;
+
+ select pattern_p, parent_id into v_pattern_p, v_parent_id
+ from site_nodes
+ where node_id = find_pattern__node_id;
+
+ if v_pattern_p = ''t'' then
+ return find_pattern__node_id;
+ else
+ return site_node__find_pattern(v_parent_id);
+ end if;
+
+end;' language 'plpgsql';
+
+
+-- function node_id
+create function site_node__node_id (varchar,integer)
+returns integer as '
+declare
+ node_id__url alias for $1;
+ node_id__parent_id alias for $2;
+ v_pos integer;
+ v_first site_nodes.name%TYPE;
+ v_rest text;
+ v_node_id integer;
+ v_pattern_p site_nodes.pattern_p%TYPE;
+ v_url text;
+ v_directory_p site_nodes.directory_p%TYPE;
+ v_trailing_slash_p boolean;
+begin
+ v_url := node_id__url;
+
+ if substr(v_url, length(v_url), 1) = ''/'' then
+ -- It ends with a / so it must be a directory.
+ v_trailing_slash_p := ''t'';
+ v_url := substr(v_url, 1, length(v_url) - 1);
+ end if;
+
+ v_pos := 1;
+
+ while v_pos <= length(v_url) and substr(v_url, v_pos, 1) <> ''/'' loop
+ v_pos := v_pos + 1;
+ end loop;
+
+ if v_pos = length(v_url) then
+ v_first := v_url;
+ v_rest := null;
+ else
+ v_first := substr(v_url, 1, v_pos - 1);
+ v_rest := substr(v_url, v_pos + 1);
+ end if;
+
+ -- begin
+ -- Is there a better way to do these freaking null compares?
+ select node_id, directory_p into v_node_id, v_directory_p
+ from site_nodes
+ where coalesce(parent_id, 3.14) = coalesce(node_id__parent_id, 3.14)
+ and coalesce(name, chr(10)) = coalesce(v_first, chr(10));
+ if NOT FOUND then
+ return site_node__find_pattern(node_id__parent_id);
+ end if;
+
+ if v_rest is null then
+ if v_trailing_slash_p = ''t'' and v_directory_p = ''f'' then
+ return site_node__find_pattern(node_id__parent_id);
+ else
+ return v_node_id;
+ end if;
+ else
+ return site_node__node_id(v_rest, v_node_id);
+ end if;
+
+
+end;' language 'plpgsql';
+
+
+-- function url
+create function site_node__url (integer)
+returns varchar as '
+declare
+ url__node_id alias for $1;
+ v_parent_id site_nodes.node_id%TYPE;
+ v_name site_nodes.name%TYPE;
+ v_directory_p site_nodes.directory_p%TYPE;
+begin
+ if url__node_id is null then
+ return '''';
+ end if;
+
+ select parent_id, name, directory_p into
+ v_parent_id, v_name, v_directory_p
+ from site_nodes
+ where node_id = url__node_id;
+
+ if v_directory_p = ''t'' then
+ return site_node__url(v_parent_id) || v_name || ''/'';
+ else
+ return site_node__url(v_parent_id) || v_name;
+ end if;
+
+end;' language 'plpgsql';
+
+
+
+-- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/site-nodes-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/site-nodes-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/site-nodes-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,20 @@
+--
+-- packages/acs-kernel/sql/site-nodes-drop.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-09-06
+-- @cvs-id site-nodes-drop.sql,v 1.5 2000/10/24 22:26:20 bquinn Exp
+--
+
+\t
+select drop_package('site_node');
+drop table site_nodes;
+
+create function inline_0 () returns integer as '
+begin
+ PERFORM acs_object_type__drop_type (''site_node'');
+ returns null;
+end;' language 'plpgsql';
+select inline_0 ();
+drop function inline_0 ();
+\t
Index: openacs-4/packages/acs-kernel/sql/postgresql/tst.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/Attic/tst.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/tst.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,78 @@
+
+
+
+select count(*)
+where exists (select 1
+ from acs_object_types t
+ where t.object_type = 'user'
+ connect by prior t.object_type = t.supertype
+ start with t.supertype = 'party');
+
+
+select count(*)
+where exists (select 1
+ from acs_object_types t
+ where t.object_type = 'user'
+ and sortkey like (select sortkey || '%'
+ from acs_object_types
+ where object_type = 'party'));
+
+
+select object_type
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = (select object_type
+ from acs_objects o
+ where o.object_id = object_id_in)
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%')
+ order by tree_sortkey desc
+
+;
+ select 1 into dummy
+ from acs_rel_types rt,
+ acs_objects o1,
+ acs_objects o2
+ where exists (select 1
+ from acs_object_types t
+ where t.object_type = o1.object_type
+ and t.tree_sortkey
+ like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = rt.object_type_one))
+ and exists (select 1
+ from acs_object_types t
+ where t.object_type = o2.object_type
+ and t.tree_sortkey
+ like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = rt.object_type_two))
+ and rt.rel_type = new.rel_type
+ and o1.object_id = new.object_id_one
+ and o2.object_id = new.object_id_two;
+
+select object_type
+ from acs_object_types o1, acs_object_types o2
+ where o1.object_type = acs_rel_types.rel_type
+ and o2.tree_sortkey <= o1.tree_sortkey
+ and o1.tree_sortkey like (o2.tree_sortkey || '%')
+ order by tree_sortkey desc
+
+
+select object_type as rel_type
+ from acs_object_types
+start with object_type = 'membership_rel'
+ or object_type = 'composition_rel'
+ connect by supertype = prior object_type
+
+select object_type as rel_type
+ from acs_object_types
+ where tree_sortkey like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = 'composition_rel')
+ or tree_sortkey like (select o.tree_sortkey || '%'
+ from acs_object_types o
+ where o.object_type = 'membership_rel');
+
+start with object_type = 'membership_rel'
+ or object_type = 'composition_rel'
+ connect by supertype = prior object_type
Index: openacs-4/packages/acs-kernel/sql/postgresql/utilities-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/utilities-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/utilities-create.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,109 @@
+--
+-- /packages/acs-kernel/sql/utilities-create.sql
+--
+-- Useful PL/SQL utility routines.
+--
+-- @author Jon Salz (jsalz@mit.edu)
+-- @creation-date 12 Aug 2000
+-- @cvs-id utilities-create.sql,v 1.3 2000/11/02 17:55:51 yon Exp
+--
+
+-- create or replace package util
+-- as
+-- function multiple_nextval(
+-- v_sequence_name in varchar2,
+-- v_count in integer)
+-- return varchar2;
+--
+-- function computehash_raw(
+-- v_value IN varchar2 )
+-- return raw;
+--
+-- function computehash(
+-- v_value IN varchar2)
+-- return varchar2;
+--
+-- function logical_negation (
+-- true_or_false IN varchar2)
+-- return varchar2;
+-- end util;
+
+-- show errors
+
+-- create or replace package body util
+-- function multiple_nextval
+create function util__multiple_nextval (varchar,integer)
+returns varchar as '
+declare
+ v_sequence_name alias for $1;
+ v_count alias for $2;
+ a_sequence_values text default '''';
+ v_rec record;
+begin
+ for counter in 1..v_count loop
+ for v_rec in EXECUTE ''select '' || quote_identifier(v_sequence_name) ''.nextval as a_seq_val''
+ LOOP
+ a_sequence_values := a_sequence_values || '''','''' || v_rec.a_seq_val;
+ exit;
+ end loop;
+ end loop;
+
+ return substr(a_sequence_values, 2);
+
+end;' language 'plpgsql';
+
+ -- This is for Password Hashing.
+ -- Make sure to run: 'loadjava -user username/password Security.class'
+ -- before running this.
+ -- Make sure you have javasyspriv and javauserpriv granted for the user.
+
+-- function computehash_raw( v_value IN varchar2 )
+-- return raw
+-- as language java
+-- name 'Security.computeSHA(java.lang.String) returns java.lang.byte[]';
+
+create function RAWTOHEX(text) returns text as '
+declare
+ arg alias for $1;
+begin
+ raise exception ''not implemented yet: depends on java code in acs classic'';
+ return '''';
+end;' language 'plpgsql';
+
+
+create function util__computehash_raw(text) returns text as '
+declare
+ arg alias for $1;
+begin
+ raise exception ''not implemented yet: depends on java code in acs classic'';
+ return '''';
+end;' language 'plpgsql';
+
+
+ -- The hashing function can be changed to MD5 by using computeMD5.
+
+create function util__computehash (varchar) returns varchar as '
+declare
+ v_value alias for $1;
+ v_hashed char(40);
+begin
+ select RAWTOHEX(util__computehash_raw(v_value)) into v_hashed;
+
+ return v_hashed;
+end;' language 'plpgsql';
+
+
+create function util__logical_negation (boolean) returns boolean as '
+declare
+ true_or_false alias for $1;
+begin
+ IF true_or_false is null THEN
+ return null;
+ ELSE IF true_or_false = ''f'' THEN
+ return ''t'';
+ ELSE
+ return ''f'';
+ END IF; END IF;
+END;' language 'plpgsql';
+
+
Index: openacs-4/packages/acs-kernel/sql/postgresql/utilities-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/utilities-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/postgresql/utilities-drop.sql 14 Mar 2001 04:39:10 -0000 1.1
@@ -0,0 +1,12 @@
+--
+-- /packages/acs-kernel/sql/utilities-drop.sql
+--
+-- Purges useful PL/SQL utility routines.
+--
+-- @author Jon Salz (jsalz@mit.edu)
+-- @creation-date 12 Aug 2000
+-- @cvs-id utilities-drop.sql,v 1.2 2000/09/19 07:23:29 ron Exp
+--
+\t
+select drop_package('util');
+\t