Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-install.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-kernel-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-kernel-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-logs-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-logs-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-metadata-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-metadata-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-objects-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-objects-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-permissions-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-permissions-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-relationships-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/acs-relationships-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/apm-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/apm-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/community-core-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/community-core-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/groups-body-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/groups-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/groups-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/journal-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/journal-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/rel-constraints-body-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/rel-constraints-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/rel-constraints-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/rel-segments-body-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/rel-segments-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/rel-segments-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/security-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/security-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/site-nodes-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/site-nodes-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/utilities-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/utilities-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,274 @@
+--
+-- 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 varchar2(100)
+ constraint acs_magic_objects_pk primary key,
+ object_id 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
+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
+ is
+ 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);
+
+ v_rel_id := membership_rel.new (
+ object_id_two => v_user_id,
+ object_id_one => acs.magic_object_id('registered_users'),
+ member_state => member_state);
+
+ acs_permission.grant_permission (
+ object_id => v_user_id,
+ grantee_id => v_user_id,
+ privilege => 'read'
+ );
+
+ acs_permission.grant_permission (
+ object_id => v_user_id,
+ grantee_id => v_user_id,
+ privilege => 'write'
+ );
+
+ return v_user_id;
+ end;
+
+ procedure remove_user (
+ user_id in users.user_id%TYPE
+ )
+ is
+ begin
+ delete from users
+ where user_id = remove_user.user_id;
+ end;
+
+ function magic_object_id (
+ name in acs_magic_objects.name%TYPE
+ ) return acs_objects.object_id%TYPE
+ is
+ 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 object_id;
+ end magic_object_id;
+
+end acs;
+/
+show errors
+
+-- ******************************************************************
+-- * Community Core API
+-- ******************************************************************
+
+create or replace 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 or replace 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.
+
+declare
+ root_id integer;
+begin
+ root_id := acs_object.new (
+ object_id => 0
+ );
+
+ insert into acs_magic_objects
+ (name, object_id)
+ values
+ ('security_context_root', 0);
+end;
+/
+show errors
+
+begin
+ --------------------------------------------------------------
+ -- Some privilege that will be fundamental to all objects. --
+ --------------------------------------------------------------
+
+ acs_privilege.create_privilege('read');
+ acs_privilege.create_privilege('write');
+ acs_privilege.create_privilege('create');
+ acs_privilege.create_privilege('delete');
+ acs_privilege.create_privilege('admin');
+
+ ---------------------------------------------------------
+ -- Administrators can read, write, create, and delete. --
+ ---------------------------------------------------------
+
+ acs_privilege.add_child('admin', 'read');
+ acs_privilege.add_child('admin', 'write');
+ acs_privilege.add_child('admin', 'create');
+ acs_privilege.add_child('admin', 'delete');
+
+ commit;
+end;
+/
+show errors
+
+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);
+
+ commit;
+end;
+/
+show errors
+
+-- Insert the site-wide group. The members of this
+-- group correspond to all registered users.
+declare
+ group_id integer;
+begin
+ group_id := acs_group.new (
+ group_id => -2,
+ group_name => 'Registered Users'
+ );
+
+ insert into acs_magic_objects
+ (name, object_id)
+ values
+ ('registered_users', -2);
+
+ commit;
+end;
+/
+show errors
+
+-- Create the default context.
+declare
+ object_id integer;
+begin
+ object_id := acs_object.new (
+ object_id => -3
+ );
+
+ insert into acs_magic_objects
+ (name, object_id)
+ values
+ ('default_context', object_id);
+
+ commit;
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,12 @@
+--
+-- packages/acs-kernel/sql/acs-drop.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-08-22
+-- @cvs-id $Id: acs-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+drop view cc_users;
+drop view registered_users;
+drop package acs;
+drop table acs_magic_objects;
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-install.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-install.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-install.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,119 @@
+--
+-- /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 $Id: acs-install.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+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 varchar2(100);
+ jobnum integer;
+begin
+ kernel_id := apm_service.new(
+ package_key => 'acs-kernel',
+ instance_name => 'ACS Kernel',
+ context_id => acs.magic_object_id('default_context')
+ );
+ commit;
+
+ apm_package.enable(kernel_id);
+
+ main_site_id := apm_service.new(
+ package_key => 'acs-subsite',
+ instance_name => 'Main Site',
+ context_id => acs.magic_object_id('default_context')
+ );
+ apm_package.enable(main_site_id);
+
+ node_id := site_node.new (
+ name => '',
+ directory_p => 't',
+ pattern_p => 't',
+ object_id => main_site_id
+ );
+
+ acs_permission.grant_permission (
+ object_id => main_site_id,
+ grantee_id => acs.magic_object_id('the_public'),
+ privilege => 'read'
+ );
+
+ admin_id := apm_service.new (
+ instance_name => 'ACS Administration',
+ package_key => 'acs-admin'
+ );
+ apm_package.enable(admin_id);
+
+ node_id := site_node.new (
+ parent_id => site_node.node_id('/'),
+ name => 'acs-admin',
+ directory_p => 't',
+ pattern_p => 't',
+ object_id => admin_id
+ );
+
+ docs_id := apm_service.new (
+ instance_name => 'ACS Core Documents',
+ package_key => 'acs-core-docs',
+ context_id => main_site_id
+ );
+
+ docs_id := site_node.new (
+ parent_id => site_node.node_id('/'),
+ name => 'doc',
+ directory_p => 't',
+ pattern_p => 't',
+ object_id => docs_id
+ );
+
+ api_doc_id := apm_service.new (
+ instance_name => 'ACS API Browser',
+ package_key => 'acs-api-browser',
+ context_id => main_site_id
+ );
+
+ 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;
+
+ acs_permission.grant_permission (
+ object_id => api_doc_id,
+ grantee_id => acs.magic_object_id ('registered_users'),
+ privilege => 'read'
+ );
+
+ api_doc_id := site_node.new (
+ parent_id => site_node.node_id('/'),
+ name => 'api-doc',
+ directory_p => 't',
+ pattern_p => 't',
+ object_id => api_doc_id
+ );
+
+ 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'
+ );
+
+ commit;
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-kernel-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-kernel-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-kernel-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,32 @@
+--
+-- /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 $Id: acs-kernel-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+set feedback off
+
+@@ acs-logs-create
+@@ acs-metadata-create
+@@ acs-objects-create
+@@ acs-relationships-create
+@@ utilities-create
+@@ community-core-create
+@@ groups-create
+@@ rel-segments-create
+@@ rel-constraints-create
+@@ groups-body-create
+@@ rel-segments-body-create
+@@ rel-constraints-body-create
+@@ acs-permissions-create
+@@ security-create
+@@ journal-create
+@@ site-nodes-create
+@@ apm-create
+@@ acs-create
+
+set feedback on
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-kernel-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-kernel-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-kernel-drop.sql 20 Mar 2001 22:51:55 -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 $Id: acs-kernel-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+@@ acs-drop
+@@ journal-drop
+@@ utilities-drop
+@@ security-drop
+@@ acs-permissions-drop
+@@ rel-constraints-drop
+@@ rel-segments-drop
+@@ groups-drop
+@@ site-nodes-drop.sql
+@@ community-core-drop
+@@ acs-relationships-drop
+@@ acs-objects-drop
+@@ acs-metadata-drop
+@@ apm-drop
+@@ acs-logs-drop
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-logs-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-logs-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-logs-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,104 @@
+--
+-- packages/acs-kernel/sql/acs-logs-create.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-10-02
+-- @cvs-id $Id: acs-logs-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+create sequence acs_log_id_seq;
+
+create table acs_logs (
+ log_id integer
+ constraint acs_logs_pk
+ primary key,
+ log_date date default sysdate not null,
+ log_level varchar2(20)
+ constraint acs_logs_log_level_ck
+ check (log_level in ('notice', 'warn', 'error',
+ 'debug')),
+ log_key varchar2(100) not null,
+ message varchar2(4000) 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
+as
+
+ procedure notice (
+ log_key in acs_logs.log_key%TYPE,
+ message in acs_logs.message%TYPE
+ )
+ is
+ begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, 'notice', notice.log_key, notice.message);
+ end;
+
+ procedure warn (
+ log_key in acs_logs.log_key%TYPE,
+ message in acs_logs.message%TYPE
+ )
+ is
+ begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, 'warn', warn.log_key, warn.message);
+ end;
+
+ procedure error (
+ log_key in acs_logs.log_key%TYPE,
+ message in acs_logs.message%TYPE
+ )
+ is
+ begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, 'error', error.log_key, error.message);
+ end;
+
+ procedure debug (
+ log_key in acs_logs.log_key%TYPE,
+ message in acs_logs.message%TYPE
+ )
+ is
+ begin
+ insert into acs_logs
+ (log_id, log_level, log_key, message)
+ values
+ (acs_log_id_seq.nextval, 'debug', debug.log_key, debug.message);
+ end;
+
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-logs-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-logs-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-logs-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,3 @@
+drop package acs_log;
+drop table acs_logs;
+drop sequence acs_log_id_seq;
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-metadata-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-metadata-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-metadata-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,689 @@
+--
+-- 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 $Id: acs-metadata-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+-- ******************************************************************
+-- * KNOWLEDGE LEVEL
+-- ******************************************************************
+
+------------------
+-- OBJECT TYPES --
+------------------
+
+create table acs_object_types (
+ object_type varchar2(100) not null
+ constraint acs_object_types_pk primary key,
+ supertype constraint acs_object_types_supertype_fk
+ references acs_object_types (object_type),
+ abstract_p char(1) default 'f' not null
+ constraint acs_obj_types_abstract_p_ck
+ check (abstract_p in ('t', 'f')),
+ pretty_name varchar2(100) not null
+ constraint acs_obj_types_pretty_name_un
+ unique,
+ pretty_plural varchar2(100) not null
+ constraint acs_obj_types_pretty_plural_un
+ unique,
+ table_name varchar2(30) not null
+ constraint acs_object_types_tbl_name_un unique,
+ id_column varchar2(30) not null,
+ package_name varchar2(30) not null
+ constraint acs_object_types_pkg_name_un unique,
+ name_method varchar2(30),
+ type_extension_table varchar2(30),
+ dynamic_p char(1) default 'f'
+ constraint acs_obj_types_dynamic_p_ck
+ check (dynamic_p in ('t', 'f'))
+);
+
+create bitmap index acs_obj_types_supertype_idx on acs_object_types (supertype);
+
+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 or replace 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 table acs_object_type_tables (
+ object_type not null constraint acs_obj_type_tbls_obj_type_fk
+ references acs_object_types (object_type),
+ table_name varchar2(30) not null,
+ id_column varchar2(30),
+ constraint acs_object_type_tables_pk
+ primary key (object_type, table_name)
+);
+
+create bitmap 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 varchar2(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.
+--
+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);
+
+ commit;
+end;
+/
+
+--create table acs_input_types (
+--);
+
+create sequence acs_attribute_id_seq;
+
+create table acs_attributes (
+ attribute_id integer not null
+ constraint acs_attributes_pk
+ primary key,
+ object_type not null
+ constraint acs_attributes_object_type_fk
+ references acs_object_types (object_type),
+ table_name varchar2(30),
+ constraint acs_attrs_obj_type_tbl_name_fk
+ foreign key (object_type, table_name) references acs_object_type_tables,
+ attribute_name varchar2(100) not null,
+ pretty_name varchar2(100) not null,
+ pretty_plural varchar2(100),
+ sort_order integer not null,
+ datatype not null
+ constraint acs_attributes_datatype_fk
+ references acs_datatypes (datatype),
+ default_value varchar2(4000),
+ 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 varchar2(13) default 'type_specific'
+ constraint acs_attributes_storage_ck
+ check (storage in ('type_specific',
+ 'generic')),
+ static_p varchar2(1) default 'f'
+ constraint acs_attributes_static_bool
+ check (static_p in ('t', 'f')),
+ column_name varchar2(30),
+ 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 bitmap index acs_attrs_obj_type_idx on acs_attributes (object_type);
+create index acs_attrs_tbl_name_idx on acs_attributes (table_name);
+create bitmap 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 not null
+ constraint asc_enum_values_attr_id_fk
+ references acs_attributes (attribute_id),
+ enum_value varchar2(1000),
+ pretty_name varchar2(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 not null constraint acs_attr_descs_obj_type_fk
+ references acs_object_types (object_type),
+ attribute_name varchar2(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 varchar2(100),
+ constraint acs_attribute_descriptions_pk
+ primary key (object_type, attribute_name, description_key),
+ description clob not null
+);
+
+create bitmap 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 or replace 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
+is
+
+ 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,
+ 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
+ )
+ is
+ v_package_name acs_object_types.package_name%TYPE;
+ begin
+ -- XXX This is a hack for losers who haven't created packages yet.
+ if package_name is null then
+ v_package_name := object_type;
+ else
+ v_package_name := 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
+ (object_type, pretty_name, pretty_plural, supertype, table_name,
+ id_column, abstract_p, type_extension_table, v_package_name,
+ name_method);
+ end create_type;
+
+ procedure drop_type (
+ object_type in acs_object_types.object_type%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ cursor c_attributes (object_type IN varchar) is
+ select attribute_name from acs_attributes where object_type = object_type;
+ begin
+
+ -- drop all the attributes associated with this type
+ for row in c_attributes (drop_type.object_type) loop
+ 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;
+ end drop_type;
+
+
+ function pretty_name (
+ object_type in acs_object_types.object_type%TYPE
+ ) return acs_object_types.pretty_name%TYPE
+ is
+ 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 pretty_name;
+
+
+ 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
+ is
+ v_result integer;
+ begin
+ select count(*) into v_result
+ from dual
+ 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);
+
+ if v_result > 0 then
+ return 't';
+ end if;
+
+ return 'f';
+
+ end is_subtype_p;
+
+end acs_object_type;
+/
+show errors
+
+
+
+create or replace package body acs_attribute
+is
+
+ 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
+ is
+ v_sort_order acs_attributes.sort_order%TYPE;
+ v_attribute_id acs_attributes.attribute_id%TYPE;
+ begin
+ if sort_order is null then
+ select nvl(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 := sort_order;
+ end if;
+
+ select acs_attribute_id_seq.nextval into v_attribute_id from dual;
+
+ 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, object_type, table_name, column_name, attribute_name,
+ pretty_name, pretty_plural, v_sort_order, datatype, default_value,
+ min_n_values, max_n_values, storage, static_p);
+
+ return v_attribute_id;
+ end create_attribute;
+
+ procedure drop_attribute (
+ object_type in varchar2,
+ attribute_name in varchar2
+ )
+ is
+ 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;
+ end drop_attribute;
+
+ 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
+ )
+ is
+ begin
+ insert into acs_attribute_descriptions
+ (object_type, attribute_name, description_key, description)
+ values
+ (add_description.object_type, add_description.attribute_name,
+ add_description.description_key, add_description.description);
+ end;
+
+ 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
+ )
+ is
+ 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;
+ end;
+
+end acs_attribute;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-metadata-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-metadata-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-metadata-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,21 @@
+--
+-- 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 $Id: acs-metadata-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+drop package acs_attribute;
+drop package acs_object_type;
+drop view acs_object_type_attributes;
+drop table acs_attribute_descriptions;
+drop table acs_enum_values;
+drop table acs_attributes;
+drop sequence 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/oracle/acs-objects-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-objects-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-objects-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,1024 @@
+--
+-- 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 $Id: acs-objects-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+-----------------------------
+-- PREDEFINED OBJECT TYPES --
+-----------------------------
+
+declare
+ attr_id acs_attributes.attribute_id%TYPE;
+begin
+ --
+ -- The ultimate supertype: object
+ --
+ acs_object_type.create_type (
+ supertype => null,
+ object_type => 'acs_object',
+ pretty_name => 'Object',
+ pretty_plural => 'Objects',
+ table_name => 'acs_objects',
+ id_column => 'object_id',
+ package_name => 'acs_object',
+ name_method => 'acs_object.default_name'
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'object_type',
+ datatype => 'string',
+ pretty_name => 'Object Type',
+ pretty_plural => 'Object Types'
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'creation_date',
+ datatype => 'date',
+ pretty_name => 'Created Date'
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'creation_ip',
+ datatype => 'string',
+ pretty_name => 'Creation IP Address'
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'last_modified',
+ datatype => 'date',
+ pretty_name => 'Last Modified On'
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'modifying_ip',
+ datatype => 'string',
+ pretty_name => 'Modifying IP Address'
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'creation_user',
+ datatype => 'integer',
+ pretty_name => 'Creation user',
+ pretty_plural => 'Creation users',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'context_id',
+ datatype => 'integer',
+ pretty_name => 'Context ID',
+ pretty_plural => 'Context IDs',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+ commit;
+end;
+/
+show errors
+
+-- ******************************************************************
+-- * OPERATIONAL LEVEL
+-- ******************************************************************
+
+-------------
+-- OBJECTS --
+-------------
+
+create sequence acs_object_id_seq cache 1000;
+
+create table acs_objects (
+ object_id integer not null
+ constraint acs_objects_pk primary key,
+ object_type not null
+ constraint acs_objects_object_type_fk
+ references acs_object_types (object_type),
+ context_id constraint acs_objects_context_id_fk
+ references acs_objects(object_id),
+ security_inherit_p char(1) default 't' not null,
+ constraint acs_objects_sec_inherit_p_ck
+ check (security_inherit_p in ('t', 'f')),
+ creation_user integer,
+ creation_date date default sysdate not null,
+ creation_ip varchar2(50),
+ last_modified date default sysdate not null,
+ modifying_user integer,
+ modifying_ip varchar2(50),
+ constraint acs_objects_context_object_un
+ unique (context_id, object_id) disable
+);
+
+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 bitmap index acs_objects_object_type_idx on acs_objects (object_type);
+
+create or replace trigger acs_objects_mod_ip_insert_tr
+before insert on acs_objects
+for each row
+begin
+ :new.modifying_ip := :new.creation_ip;
+end acs_objects_mod_ip_insert_tr;
+/
+show errors
+
+create or replace trigger acs_objects_last_mod_update_tr
+before update on acs_objects
+for each row
+begin
+ :new.last_modified := sysdate;
+end 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 not null
+ constraint acs_obj_context_idx_obj_id_fk
+ references acs_objects(object_id),
+ ancestor_id 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)
+) organization index;
+
+create index acs_obj_ctx_idx_ancestor_idx on acs_object_context_index (ancestor_id);
+
+create or replace view acs_object_paths
+as select object_id, ancestor_id, n_generations
+ from acs_object_context_index;
+
+create or replace view acs_object_contexts
+as select object_id, ancestor_id, n_generations
+ from acs_object_context_index
+ where object_id != ancestor_id;
+
+create or replace trigger acs_objects_context_id_in_tr
+after insert on acs_objects
+for each row
+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;
+ elsif :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;
+/
+show errors
+
+create or replace trigger acs_objects_context_id_up_tr
+after update on acs_objects
+for each row
+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;
+ elsif :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;
+/
+show errors
+
+create or replace trigger acs_objects_context_id_del_tr
+before delete on acs_objects
+for each row
+begin
+ delete from acs_object_context_index
+ where object_id = :old.object_id;
+end;
+/
+show errors
+
+----------------------
+-- ATTRIBUTE VALUES --
+----------------------
+
+create sequence acs_attribute_value_id_seq;
+
+create table acs_attribute_values (
+ object_id not null
+ constraint acs_attr_values_obj_id_fk
+ references acs_objects (object_id) on delete cascade,
+ attribute_id not null
+ constraint acs_attr_values_attr_id_fk
+ references acs_attributes (attribute_id),
+ attr_value varchar2(4000),
+ 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 not null
+ constraint acs_static_a_v_obj_id_fk
+ references acs_object_types (object_type) on delete cascade,
+ attribute_id not null
+ constraint acs_static_a_v_attr_id_fk
+ references acs_attributes (attribute_id),
+ attr_value varchar2(4000),
+ 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
+as
+
+ procedure initialize_attributes (
+ object_id in acs_objects.object_id%TYPE
+ )
+ is
+ 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;
+ end;
+
+ end initialize_attributes;
+
+ 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
+ is
+ v_object_id acs_objects.object_id%TYPE;
+ begin
+ if object_id is null then
+ select acs_object_id_seq.nextval
+ into v_object_id
+ from dual;
+ else
+ v_object_id := object_id;
+ end if;
+
+ insert into acs_objects
+ (object_id, object_type, context_id,
+ creation_date, creation_user, creation_ip)
+ values
+ (v_object_id, object_type, context_id,
+ creation_date, creation_user, creation_ip);
+
+ acs_object.initialize_attributes(v_object_id);
+
+ return v_object_id;
+ end new;
+
+ procedure delete (
+ object_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+
+ -- Delete dynamic/generic attributes
+ delete from acs_attribute_values where object_id = acs_object.delete.object_id;
+
+ for object_type
+ in (select table_name, id_column
+ from acs_object_types
+ start with object_type = (select object_type
+ from acs_objects o
+ where o.object_id = acs_object.delete.object_id)
+ connect by object_type = prior supertype)
+ loop
+ -- Delete from the table.
+ execute immediate 'delete from ' || object_type.table_name ||
+ ' where ' || object_type.id_column || ' = :object_id'
+ using in object_id;
+ end loop;
+ end delete;
+
+ function name (
+ object_id in acs_objects.object_id%TYPE
+ )
+ return varchar2
+ is
+ object_name varchar2(500);
+ v_object_id integer := object_id;
+ 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.
+ --
+ for object_type
+ in (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)
+ loop
+ if object_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 immediate 'select ' || object_type.name_method || '(:1) from dual'
+ execute immediate 'begin :1 := ' || object_type.name_method || '(:2); end;'
+ using out object_name, in object_id;
+ --into object_name
+
+ exit;
+ end if;
+ end loop;
+
+ return object_name;
+ end name;
+
+ function default_name (
+ object_id in acs_objects.object_id%TYPE
+ ) return varchar2
+ is
+ 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 default_name;
+
+ 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
+ )
+ is
+ v_object_type acs_attributes.object_type%TYPE;
+ v_static acs_attributes.static_p%TYPE := null;
+ v_attr_id acs_attributes.attribute_id%TYPE := null;
+ v_storage acs_attributes.storage%TYPE := null;
+ v_attr_name acs_attributes.attribute_name%TYPE := null;
+ v_id_column varchar2(200) := null;
+ v_sql varchar2(4000) := null;
+ v_return varchar2(4000) := null;
+
+ -- Fetch the most inherited attribute
+ cursor c_attribute is
+ select
+ a.attribute_id, a.static_p, a.storage, a.table_name, a.attribute_name,
+ a.object_type, a.column_name, t.id_column
+ from
+ acs_attributes a,
+ (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)
+ ) t
+ where
+ a.attribute_name = attribute_name_in
+ and
+ a.object_type = t.object_type;
+
+ begin
+
+ -- Determine the attribute parameters
+ open c_attribute;
+ fetch c_attribute into
+ v_attr_id, v_static, v_storage, v_table_name, v_attr_name,
+ v_object_type, v_column, v_id_column;
+ if c_attribute%NOTFOUND then
+ close c_attribute;
+ raise_application_error (-20000,
+ 'No such attribute ' || v_object_type || '::' || attribute_name_in ||
+ ' in acs_object.get_attribute_storage.');
+ end if;
+ close c_attribute;
+
+ -- 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;
+ else
+ raise_application_error(-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;
+
+ 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;
+
+ exception when no_data_found then
+ raise_application_error(-20000, 'No data found for attribute ' ||
+ v_object_type || '::' || attribute_name_in ||
+ ' in acs_object.get_attribute_storage');
+
+ end get_attribute_storage;
+
+ -- 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
+ is
+ v_table_name varchar2(200);
+ v_column varchar2(200);
+ v_key_sql varchar2(4000);
+ v_return varchar2(4000);
+ begin
+
+ get_attribute_storage(object_id_in, attribute_name_in,
+ v_column, v_table_name, v_key_sql);
+
+ begin
+ execute immediate 'select '
+ || v_column || ' from ' || v_table_name || ' where ' || v_key_sql
+ into
+ v_return;
+ exception when no_data_found then
+ return null;
+ end;
+
+ return v_return;
+ end get_attribute;
+
+ 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
+ )
+ is
+ v_table_name varchar2(200);
+ v_column varchar2(200);
+ v_key_sql varchar2(4000);
+ v_return varchar2(4000);
+ v_dummy integer;
+ begin
+
+ get_attribute_storage(object_id_in, attribute_name_in,
+ v_column, v_table_name, v_key_sql);
+
+ execute immediate 'update '
+ || v_table_name || ' set ' || v_column || ' = :value where ' || v_key_sql
+ using value_in;
+
+ end set_attribute;
+
+ function check_context_index (
+ object_id in acs_objects.object_id%TYPE,
+ ancestor_id in acs_objects.object_id%TYPE,
+ n_generations in integer
+ ) return char
+ is
+ n_rows integer;
+ n_gens integer;
+ begin
+ -- Verify that this row exists in the index.
+ select decode(count(*),0,0,1) 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
+ 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
+ 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;
+
+ function check_object_ancestors (
+ object_id in acs_objects.object_id%TYPE,
+ ancestor_id in acs_objects.object_id%TYPE,
+ n_generations in integer
+ ) return char
+ is
+ context_id acs_objects.context_id%TYPE;
+ security_inherit_p acs_objects.security_inherit_p%TYPE;
+ n_rows integer;
+ n_gens integer;
+ result char(1);
+ 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 ancestor_id = 0 then
+ if context_id is null then
+ result := 't';
+ else
+ -- This can be a constraint, can''t it?
+ 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 check_context_index(object_id, ancestor_id, n_generations) = 'f' then
+ result := 'f';
+ end if;
+
+ if check_object_ancestors(object_id, context_id,
+ n_generations + 1) = 'f' then
+ result := 'f';
+ end if;
+ end if;
+
+ return result;
+ end;
+
+ function check_object_descendants (
+ object_id in acs_objects.object_id%TYPE,
+ descendant_id in acs_objects.object_id%TYPE,
+ n_generations in integer
+ ) return char
+ is
+ result char(1);
+ 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 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 check_object_descendants(object_id, obj.object_id,
+ n_generations + 1) = 'f' then
+ result := 'f';
+ end if;
+ end loop;
+
+ return result;
+ end;
+
+ function check_path (
+ object_id in acs_objects.object_id%TYPE,
+ ancestor_id in acs_objects.object_id%TYPE
+ ) return char
+ is
+ context_id acs_objects.context_id%TYPE;
+ security_inherit_p acs_objects.security_inherit_p%TYPE;
+ begin
+ if object_id = 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 check_path(context_id, ancestor_id);
+ end;
+
+ function check_representation (
+ object_id in acs_objects.object_id%TYPE
+ ) return char
+ is
+ result char(1);
+ object_type acs_objects.object_type%TYPE;
+ n_rows integer;
+ begin
+ result := 't';
+ acs_log.notice('acs_object.check_representation',
+ 'Running acs_object.check_representation on object_id = ' ||
+ 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;
+
+ 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
+ execute immediate 'select decode(count(*),0,0,1) from ' || t.table_name ||
+ ' where ' || t.id_column || ' = ' || object_id
+ into n_rows;
+
+ if n_rows = 0 then
+ result := 'f';
+ acs_log.error('acs_object.check_representation',
+ 'Table ' || t.table_name || ' (primary storage for ' ||
+ t.object_type || ') doesn''t have a row for object ' ||
+ object_id || ' of type ' || object_type || '.');
+ end if;
+ end loop;
+
+ 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 check_object_ancestors(object_id, 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 check_object_descendants(object_id, 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 check_path(row.object_id, row.ancestor_id) = 'f' then
+ 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;
+
+ acs_log.notice('acs_object.check_representation',
+ 'Done running acs_object.check_representation ' ||
+ 'on object_id = ' || object_id || '.');
+ return result;
+ end check_representation;
+
+end acs_object;
+/
+show errors
+
+-------------------
+-- MISCELLANEOUS --
+-------------------
+
+create table general_objects (
+ object_id not null
+ constraint general_objects_object_id_fk
+ references acs_objects (object_id)
+ constraint general_objects_pk
+ primary key,
+ on_which_table varchar2(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/oracle/acs-objects-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-objects-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-objects-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,25 @@
+--
+-- 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 $Id: acs-objects-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+drop table general_objects;
+drop package acs_object;
+drop table acs_static_attr_values;
+drop table acs_attribute_values;
+drop sequence 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 sequence acs_object_id_seq;
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-permissions-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-permissions-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-permissions-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,391 @@
+--
+-- 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 $Id: acs-permissions-create.sql,v 1.1 2001/03/20 22:51:55 donb 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 varchar2(100) not null constraint acs_privileges_pk
+ primary key,
+ pretty_name varchar2(100),
+ pretty_plural varchar2(100)
+);
+
+create table acs_privilege_hierarchy (
+ privilege not null constraint acs_priv_hier_priv_fk
+ references acs_privileges (privilege),
+ child_privilege not null constraint acs_priv_hier_child_priv_fk
+ references acs_privileges (privilege),
+ constraint acs_privilege_hierarchy_pk
+ primary key (privilege, child_privilege)
+);
+
+create bitmap 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
+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
+ )
+ is
+ begin
+ insert into acs_privileges
+ (privilege, pretty_name, pretty_plural)
+ values
+ (create_privilege.privilege,
+ create_privilege.pretty_name,
+ create_privilege.pretty_plural);
+ end;
+
+ procedure drop_privilege (
+ privilege in acs_privileges.privilege%TYPE
+ )
+ is
+ begin
+ delete from acs_privileges
+ where privilege = drop_privilege.privilege;
+ end;
+
+ procedure add_child (
+ privilege in acs_privileges.privilege%TYPE,
+ child_privilege in acs_privileges.privilege%TYPE
+ )
+ is
+ begin
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ (add_child.privilege, add_child.child_privilege);
+ end;
+
+ procedure remove_child (
+ privilege in acs_privileges.privilege%TYPE,
+ child_privilege in acs_privileges.privilege%TYPE
+ )
+ is
+ begin
+ delete from acs_privilege_hierarchy
+ where privilege = remove_child.privilege
+ and child_privilege = remove_child.child_privilege;
+ end;
+
+
+end;
+/
+show errors
+
+
+------------------------------------
+-- OPERATIONAL LEVEL: PERMISSIONS --
+------------------------------------
+
+create table acs_permissions (
+ object_id not null
+ constraint acs_permissions_on_what_id_fk
+ references acs_objects (object_id),
+ grantee_id not null
+ constraint acs_permissions_grantee_id_fk
+ references parties (party_id),
+ privilege 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 bitmap index acs_permissions_privilege_idx on acs_permissions (privilege);
+
+create or replace 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 or replace 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 or replace 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 or replace 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 or replace 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 or replace 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 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
+as
+
+ procedure grant_permission (
+ object_id acs_permissions.object_id%TYPE,
+ grantee_id acs_permissions.grantee_id%TYPE,
+ privilege acs_permissions.privilege%TYPE
+ )
+ as
+ begin
+ insert into acs_permissions
+ (object_id, grantee_id, privilege)
+ values
+ (object_id, grantee_id, privilege);
+ exception
+ when dup_val_on_index then
+ return;
+ end grant_permission;
+
+ procedure revoke_permission (
+ object_id acs_permissions.object_id%TYPE,
+ grantee_id acs_permissions.grantee_id%TYPE,
+ privilege acs_permissions.privilege%TYPE
+ )
+ as
+ begin
+ delete from acs_permissions
+ where object_id = revoke_permission.object_id
+ and grantee_id = revoke_permission.grantee_id
+ and privilege = revoke_permission.privilege;
+ end revoke_permission;
+
+ function permission_p (
+ object_id acs_objects.object_id%TYPE,
+ party_id parties.party_id%TYPE,
+ privilege acs_privileges.privilege%TYPE
+ ) return char
+ as
+ exists_p char(1);
+ 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 decode(count(*),0,'f','t') 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;
+
+end acs_permission;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-permissions-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-permissions-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-permissions-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,23 @@
+--
+-- packages/acs-kernel/sql/acs-permissions-drop.sql
+--
+-- @creation-date 2000-08-13
+--
+-- @author rhs@mit.edu
+--
+-- @cvs-id $Id: acs-permissions-drop.sql,v 1.1 2001/03/20 22:51:55 donb 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;
+drop package acs_permission;
+drop table acs_permissions;
+--drop view acs_privilege_method_map;
+--drop table acs_privilege_method_rules;
+drop package acs_privilege;
+drop table acs_privilege_hierarchy;
+drop table acs_privileges;
+--drop table acs_methods;
Index: openacs-4/packages/acs-kernel/sql/oracle/acs-relationships-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-relationships-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/acs-relationships-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,506 @@
+--
+-- packages/acs-kernel/sql/acs-relationships-create.sql
+--
+-- XXX Fill this in later.
+--
+-- @creation-date 2000-08-13
+--
+-- @author rhs@mit.edu
+--
+-- @cvs-id $Id: acs-relationships-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+----------------------------------------------------------------
+-- KNOWLEDGE LEVEL: RELATIONSHIP TYPES AND RELATIONSHIP RULES --
+----------------------------------------------------------------
+
+create table acs_rel_roles (
+ role varchar2(100) not null
+ constraint acs_rel_roles_pk primary key,
+ pretty_name varchar2(100) not null,
+ pretty_plural varchar2(100) not null
+);
+
+create table acs_rel_types (
+ rel_type varchar2(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 not null
+ constraint acs_rel_types_obj_type_1_fk
+ references acs_object_types (object_type),
+ role_one 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 not null
+ constraint acs_rel_types_obj_type_2_fk
+ references acs_object_types (object_type),
+ role_two 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 bitmap index acs_rel_types_objtypeone_idx on acs_rel_types (object_type_one);
+create bitmap index acs_rel_types_role_one_idx on acs_rel_types (role_one);
+create bitmap index acs_rel_types_objtypetwo_idx on acs_rel_types (object_type_two);
+create bitmap 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 +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 + ) + is + begin + insert into acs_rel_roles + (role, pretty_name, pretty_plural) + values + (create_role.role, nvl(create_role.pretty_name,create_role.role), nvl(create_role.pretty_plural,create_role.role)); + end; + + procedure drop_role ( + role in acs_rel_roles.role%TYPE + ) + is + begin + delete from acs_rel_roles + where role = drop_role.role; + end; + + function role_pretty_name ( + role in acs_rel_roles.role%TYPE + ) return acs_rel_roles.pretty_name%TYPE + is + 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 role_pretty_name; + + + function role_pretty_plural ( + role in acs_rel_roles.role%TYPE + ) return acs_rel_roles.pretty_plural%TYPE + is + 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 role_pretty_plural; + + 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 + ) + is + begin + acs_object_type.create_type( + object_type => rel_type, + pretty_name => pretty_name, + pretty_plural => pretty_plural, + supertype => supertype, + table_name => table_name, + id_column => id_column, + package_name => package_name, + abstract_p => abstract_p, + type_extension_table => type_extension_table, + name_method => 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); + end; + + procedure drop_type ( + rel_type in acs_rel_types.rel_type%TYPE, + cascade_p in char default 'f' + ) + is + begin + -- XXX do cascade_p + delete from acs_rel_types + where rel_type = drop_type.rel_type; + + acs_object_type.drop_type(drop_type.rel_type, drop_type.cascade_p); + end; + +end acs_rel_type; +/ +show errors + +begin + acs_rel_type.create_type ( + rel_type => 'relationship', + pretty_name => 'Relationship', + pretty_plural => 'Relationships', + supertype => 'acs_object', + table_name => 'acs_rels', + id_column => 'rel_id', + package_name => 'acs_rel', + type_extension_table => 'acs_rel_types', + object_type_one => 'acs_object', + min_n_rels_one => 0, + max_n_rels_one => null, + object_type_two => 'acs_object', + min_n_rels_two => 0, + max_n_rels_two => null + ); + + commit; +end; +/ +show errors + +-------------------------------------- +-- OPERATIONAL LEVEL: RELATIONSHIPS -- +-------------------------------------- + +create sequence acs_rel_id_seq; + +create table acs_rels ( + rel_id not null + constraint acs_rels_rel_id_fk + references acs_objects (object_id) + constraint acs_rels_pk primary key, + rel_type not null + constraint acs_rels_rel_type_fk + references acs_rel_types (rel_type), + object_id_one not null + constraint acs_object_rels_one_fk + references acs_objects (object_id), + object_id_two 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 or replace trigger acs_rels_in_tr +before insert or update on acs_rels +for each row +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; + +exception + when NO_DATA_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_application_error (-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; +/ +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, + 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 +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, + creation_ip in acs_objects.creation_ip%TYPE default null + ) return acs_rels.rel_id%TYPE + is + 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 ( + object_id => rel_id, + object_type => rel_type, + context_id => context_id, + creation_user => creation_user, + creation_ip => creation_ip + ); + + 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; + + procedure delete ( + rel_id in acs_rels.rel_id%TYPE + ) + is + begin + acs_object.delete(rel_id); + end; + +end; +/ +show errors + + +----------- +-- 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 or replace 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 or replace 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/oracle/acs-relationships-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/acs-relationships-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/acs-relationships-drop.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,16 @@ +-- +-- packages/acs-kernel/sql/acs-relationships-drop.sql +-- +-- @creation-date 2000-08-13 +-- +-- @author rhs@mit.edu +-- +-- @cvs-id $Id: acs-relationships-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $ +-- + +drop package acs_rel; +drop package acs_rel_type; +drop table acs_rels; +drop sequence acs_rel_id_seq; +drop table acs_rel_types; +drop table acs_rel_roles; Index: openacs-4/packages/acs-kernel/sql/oracle/apm-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/apm-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/apm-create.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,2624 @@ +-- +-- /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 $Id: apm-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $ + +----------------------------- +-- PACKAGE OBJECT -- +----------------------------- + +----------------------------- +-- Knowledge Level -- +----------------------------- + +create table apm_package_types ( + package_key varchar2(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 varchar2(100) + constraint apm_package_types_pretty_pl_un unique, + package_uri varchar2(1500) + constraint apm_packages_types_p_uri_nn not null + constraint apm_packages_types_p_uri_un unique, + package_type varchar2(300) + constraint apm_packages_pack_type_ck + check (package_type in ('apm_application', 'apm_service')), + spec_file_path varchar2(1500), + spec_file_mtime integer, + singleton_p char(1) default 'f' not null + constraint apm_packages_site_avail_p_ck + check (singleton_p in ('t', 'f')) +); + +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. +'; + + +begin +-- Create a new object type for packages. + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'apm_package', + pretty_name => 'Package', + pretty_plural => 'Packages', + table_name => 'APM_PACKAGES', + id_column => 'package_id', + package_name => 'apm_package', + type_extension_table => 'apm_package_types', + name_method => 'apm_package.name' + ); +end; +/ +show errors; + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin +-- Register the meta-data for APM-packages + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package', + attribute_name => 'package_key', + datatype => 'string', + pretty_name => 'Package Key', + pretty_plural => 'Package Keys' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package', + attribute_name => 'package_uri', + datatype => 'string', + pretty_name => 'Package URI', + pretty_plural => 'Package URIs' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package', + attribute_name => 'spec_file_path', + datatype => 'string', + pretty_name => 'Specification File Path', + pretty_plural => 'Specification File Paths' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package', + attribute_name => 'spec_file_mtime', + datatype => 'number', + pretty_name => 'Specification File Modified Time', + pretty_plural => 'Specification File Modified Times' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package', + attribute_name => 'singleton_p', + datatype => 'boolean', + pretty_name => 'Singleton', + pretty_plural => 'Singletons' + ); + +end; +/ +show errors; + +create table apm_packages ( + package_id constraint apm_packages_package_id_fk + references acs_objects(object_id) + constraint apm_packages_pack_id_pk primary key, + package_key constraint apm_packages_package_key_fk + references apm_package_types(package_key), + instance_name varchar2(300) + constraint apm_packages_inst_name_nn not null, + enabled_p char(1) default 'f' + constraint apm_packages_enabled_p_ck + check (enabled_p in ('t', 'f')) +); + +create bitmap 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 varchar2(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 varchar2(100) + constraint apm_package_vers_ver_name_nn not null, + version_uri varchar2(1500) + constraint apm_package_vers_ver_uri_nn not null + constraint apm_package_vers_ver_uri_un unique, + summary varchar2(3000), + description_format varchar2(100) + constraint apm_package_vers_desc_for_ck + check (description_format in ('text/html', 'text/plain')), + description varchar2(4000), + release_date date, + vendor varchar2(500), + vendor_uri varchar2(1500), + enabled_p char(1) default 'f' + constraint apm_package_vers_enabled_p_nn not null + constraint apm_package_vers_enabled_p_ck check(enabled_p in ('t','f')), + installed_p char(1) default 'f' + constraint apm_package_vers_inst_p_nn not null + constraint apm_package_vers_inst_p_ck check(installed_p in ('t','f')), + tagged_p char(1) default 'f' + constraint apm_package_vers_tagged_p_nn not null + constraint apm_package_vers_tagged_p_ck check(tagged_p in ('t','f')), + imported_p char(1) default 'f' + constraint apm_package_vers_imp_p_nn not null + constraint apm_package_vers_imp_p_ck check(imported_p in ('t','f')), + data_model_loaded_p char(1) default 'f' + constraint apm_package_vers_dml_p_nn not null + constraint apm_package_vers_dml_p_ck check(data_model_loaded_p in ('t','f')), + cvs_import_results clob, + activation_date date, + deactivation_date date, + distribution_tarball blob, + distribution_uri varchar2(1500), + distribution_date date, + 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. + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'apm_package_version', + pretty_name => 'Package Version', + pretty_plural => 'Package Versions', + table_name => 'APM_PACKAGE_VERSIONS', + id_column => 'version_id', + package_name => 'APM_PACKAGE_VERSION' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'package_key', + datatype => 'string', + pretty_name => 'Package Key', + pretty_plural => 'Package Keys' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'version_name', + datatype => 'string', + pretty_name => 'Version Name', + pretty_plural => 'Version Names' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'version_uri', + datatype => 'string', + pretty_name => 'Version URI', + pretty_plural => 'Version URIs' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'summary', + datatype => 'string', + pretty_name => 'Summary', + pretty_plural => 'Summaries' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'description_format', + datatype => 'string', + pretty_name => 'Description Format', + pretty_plural => 'Description Formats' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'description', + datatype => 'string', + pretty_name => 'Description', + pretty_plural => 'Descriptions' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'vendor', + datatype => 'string', + pretty_name => 'Vendor', + pretty_plural => 'Vendors' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'vendor_uri', + datatype => 'string', + pretty_name => 'Vendor URI', + pretty_plural => 'Vendor URIs' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'enabled_p', + datatype => 'string', + pretty_name => 'Enabled', + pretty_plural => 'Enabled' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'activation_date', + datatype => 'date', + pretty_name => 'Activation Date', + pretty_plural => 'Activation Dates' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'deactivation_date', + datatype => 'string', + pretty_name => 'Deactivation Date', + pretty_plural => 'Deactivation Dates' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'distribution_uri', + datatype => 'string', + pretty_name => 'Distribution URI', + pretty_plural => 'Distribution URIs' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_package_version', + attribute_name => 'distribution_date', + datatype => 'date', + pretty_name => 'Distribution Date', + pretty_plural => 'Distribution Dates' + ); + +end; +/ +show errors; + +-- Who owns a version? +create table apm_package_owners ( + version_id 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 varchar2(1500), + owner_name varchar2(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 or replace 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, + 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 or replace 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 varchar2(50) + constraint apm_package_file_types_pk primary key, + pretty_name varchar2(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. +'; + +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'); + commit; +end; +/ +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 constraint apm_package_files_ver_id_fk references apm_package_versions + on delete cascade + constraint apm_package_files_ver_id_nn not null, + path varchar2(1500) + constraint apm_package_files_path_nn not null, + file_type constraint apm_package_files_type_fk references apm_package_file_types, + constraint apm_package_files_un unique(version_id, path) +); + +create bitmap 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 or replace view apm_file_info as + select f.*, p.package_key, 'packages/' || p.package_key || '/' || f.path 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 constraint apm_parameters_fk + references acs_objects(object_id) + constraint apm_parameters_pk primary key, + package_key varchar2(100) + constraint apm_pack_param_pack_key_nn not null + constraint apm_pack_param_type_fk + references apm_package_types (package_key), + parameter_name varchar2(100) + constraint apm_pack_params_name_nn not null, + description varchar2(2000), + section_name varchar2(200), + datatype varchar2(100) not null + constraint apm_parameter_datatype_ck + check(datatype in ('number', 'string')), + default_value varchar2(4000), + 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 constraint apm_parameter_values_fk + references acs_objects(object_id) + constraint apm_parameter_values_pk primary key, + package_id constraint apm_pack_values_obj_id_fk + references apm_packages (package_id) on delete cascade, + parameter_id constraint apm_pack_values_parm_id_fk + references apm_parameters (parameter_id), + attr_value varchar2(4000), + 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. + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'apm_parameter', + pretty_name => 'Package Parameter', + pretty_plural => 'Package Parameters', + table_name => 'APM_PARAMETERS', + id_column => 'parameter_id', + package_name => 'apm_parameter' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter', + attribute_name => 'package_key', + datatype => 'string', + pretty_name => 'Package Key', + pretty_plural => 'Package Keys' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter', + attribute_name => 'parameter_name', + datatype => 'string', + pretty_name => 'Parameter Name', + pretty_plural => 'Parameter Name' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter', + attribute_name => 'datatype', + datatype => 'string', + pretty_name => 'Datatype', + pretty_plural => 'Datatypes' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter', + attribute_name => 'default_value', + datatype => 'string', + pretty_name => 'Default Value', + pretty_plural => 'Default Values' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter', + attribute_name => 'min_n_values', + datatype => 'number', + pretty_name => 'Minimum Number of Values', + pretty_plural => 'Minimum Numer of Values Settings', + default_value => 1 + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter', + attribute_name => 'max_n_values', + datatype => 'string', + pretty_name => 'Maximum Number of Values', + pretty_plural => 'Maximum Number of Values Settings', + default_value => 1 + ); +end; +/ +show errors; + + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'apm_parameter_value', + pretty_name => 'APM Package Parameter Value', + pretty_plural => 'APM Package Parameter Values', + table_name => 'apm_parameter_values', + id_column => 'value_id', + package_name => 'apm_parameter_value' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter_value', + attribute_name => 'package_id', + datatype => 'number', + pretty_name => 'Package ID', + pretty_plural => 'Package IDs' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter_value', + attribute_name => 'parameter_id', + datatype => 'number', + pretty_name => 'Parameter ID', + pretty_plural => 'Parameter IDs' + ); + + attr_id := acs_attribute.create_attribute( + object_type => 'apm_parameter_value', + attribute_name => 'attr_value', + datatype => 'string', + pretty_name => 'Parameter Value', + pretty_plural => 'Parameter Values' + ); +end; +/ +show errors; + +create table apm_package_dependencies ( + dependency_id integer + constraint apm_package_deps_id_pk primary key, + version_id 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 varchar2(20) + constraint apm_package_deps_type_nn not null + constraint apm_package_deps_type_ck check(dependency_type in ('provides','requires')), + service_uri varchar2(1500) + constraint apm_package_deps_uri_nn not null, + service_version varchar2(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. +'; + + +begin +-- Create a new object type for applications. + acs_object_type.create_type ( + supertype => 'apm_package', + object_type => 'apm_application', + pretty_name => 'Application', + pretty_plural => 'Applications', + table_name => 'apm_applications', + id_column => 'application_id', + package_name => 'apm_application' + ); +end; +/ +show errors + + +begin +-- Create a new object type for services. + acs_object_type.create_type ( + supertype => 'apm_package', + object_type => 'apm_service', + pretty_name => 'Service', + pretty_plural => 'Services', + table_name => 'apm_services', + id_column => 'service_id', + package_name => 'apm_service' + ); +end; +/ +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 +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 + ) + is + begin + apm_package_type.create_type( + package_key => register_package.package_key, + pretty_name => register_package.pretty_name, + pretty_plural => register_package.pretty_plural, + package_uri => register_package.package_uri, + package_type => register_package.package_type, + singleton_p => register_package.singleton_p, + spec_file_path => register_package.spec_file_path, + spec_file_mtime => spec_file_mtime + ); + end register_package; + + 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 + is + begin + + return apm_package_type.update_type( + package_key => update_package.package_key, + pretty_name => update_package.pretty_name, + pretty_plural => update_package.pretty_plural, + package_uri => update_package.package_uri, + package_type => update_package.package_type, + singleton_p => update_package.singleton_p, + spec_file_path => update_package.spec_file_path, + spec_file_mtime => update_package.spec_file_mtime + ); + + end update_package; + + + procedure unregister_package ( + package_key in apm_package_types.package_key%TYPE, + cascade_p in char default 't' + ) + is + begin + apm_package_type.drop_type( + package_key => unregister_package.package_key, + cascade_p => unregister_package.cascade_p + ); + end unregister_package; + + function register_p ( + package_key in apm_package_types.package_key%TYPE + ) return integer + is + v_register_p integer; + begin + select decode(count(*),0,0,1) into v_register_p from apm_package_types + where package_key = register_p.package_key; + return v_register_p; + end register_p; + + 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 + ) + is + begin + apm.register_package( + package_key => register_application.package_key, + pretty_name => register_application.pretty_name, + pretty_plural => register_application.pretty_plural, + package_uri => register_application.package_uri, + package_type => 'apm_application', + singleton_p => register_application.singleton_p, + spec_file_path => register_application.spec_file_path, + spec_file_mtime => register_application.spec_file_mtime + ); + end register_application; + + procedure unregister_application ( + package_key in apm_package_types.package_key%TYPE, + cascade_p in char default 'f' + ) + is + begin + apm.unregister_package ( + package_key => unregister_application.package_key, + cascade_p => unregister_application.cascade_p + ); + end unregister_application; + + 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 + ) + is + begin + apm.register_package( + package_key => register_service.package_key, + pretty_name => register_service.pretty_name, + pretty_plural => register_service.pretty_plural, + package_uri => register_service.package_uri, + package_type => 'apm_service', + singleton_p => register_service.singleton_p, + spec_file_path => register_service.spec_file_path, + spec_file_mtime => register_service.spec_file_mtime + ); + end register_service; + + procedure unregister_service ( + package_key in apm_package_types.package_key%TYPE, + cascade_p in char default 'f' + ) + is + begin + apm.unregister_package ( + package_key => unregister_service.package_key, + cascade_p => unregister_service.cascade_p + ); + end unregister_service; + + -- 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 + is + v_parameter_id apm_parameters.parameter_id%TYPE; + cursor all_parameters is + select ap.package_id, p.parameter_id, p.default_value + from apm_parameters p, apm_parameter_values v, apm_packages ap + where p.package_key = ap.package_key + and p.parameter_id = v.parameter_id (+) + and v.attr_value is null + and p.package_key = register_parameter.package_key; + begin + -- Create the new parameter. + v_parameter_id := acs_object.new( + object_id => parameter_id, + object_type => 'apm_parameter' + ); + + 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, register_parameter.description, + register_parameter.package_key, register_parameter.datatype, + register_parameter.default_value, register_parameter.section_name, + register_parameter.min_n_values, register_parameter.max_n_values); + -- Propagate parameter to new instances. + for cur_val in all_parameters + loop + apm.set_value( + package_id => cur_val.package_id, + parameter_id => cur_val.parameter_id, + attr_value => cur_val.default_value + ); + end loop; + return v_parameter_id; + end register_parameter; + + 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 + is + begin + update apm_parameters + set parameter_name = nvl(update_parameter.parameter_name, parameter_name), + default_value = nvl(update_parameter.default_value, default_value), + datatype = nvl(update_parameter.datatype, datatype), + description = nvl(update_parameter.description, description), + section_name = nvl(update_parameter.section_name, section_name), + min_n_values = nvl(update_parameter.min_n_values, min_n_values), + max_n_values = nvl(update_parameter.max_n_values, max_n_values) + where parameter_id = update_parameter.parameter_id; + return parameter_id; + end; + + function parameter_p( + package_key in apm_package_types.package_key%TYPE, + parameter_name in apm_parameters.parameter_name%TYPE + ) return integer + is + v_parameter_p integer; + begin + select decode(count(*),0,0,1) 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 parameter_p; + + procedure unregister_parameter ( + parameter_id in apm_parameters.parameter_id%TYPE + default null + ) + is + begin + delete from apm_parameter_values + where parameter_id = unregister_parameter.parameter_id; + delete from apm_parameters + where parameter_id = unregister_parameter.parameter_id; + acs_object.delete(parameter_id); + end unregister_parameter; + + function id_for_name ( + parameter_name in apm_parameters.parameter_name%TYPE, + package_key in apm_parameters.package_key%TYPE + ) return apm_parameters.parameter_id%TYPE + is + 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 id_for_name; + + 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 + is + 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 get_value; + + 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 + is + 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( + parameter_id => v_parameter_id, + package_id => get_value.package_id + ); + end get_value; + + + -- 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 + ) + is + 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 + when NO_DATA_FOUND + then + v_value_id := apm_parameter_value.new( + package_id => set_value.package_id, + parameter_id => set_value.parameter_id, + attr_value => set_value.attr_value + ); + end set_value; + + 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 + ) + is + 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); + apm.set_value( + parameter_id => v_parameter_id, + package_id => set_value.package_id, + attr_value => set_value.attr_value + ); + exception + when NO_DATA_FOUND + then + RAISE_APPLICATION_ERROR(-20000, 'The specified package ' || set_value.package_id || + ' does not exist in the system.'); + end set_value; +end apm; +/ +show errors + +create or replace package body apm_package +as + procedure initialize_parameters ( + package_id in apm_packages.package_id%TYPE, + package_key in apm_package_types.package_key%TYPE + ) + is + v_value_id apm_parameter_values.value_id%TYPE; + cursor cur is + select parameter_id, default_value + from apm_parameters + where package_key = initialize_parameters.package_key; + begin + -- need to initialize all params for this type + for cur_val in cur + loop + v_value_id := apm_parameter_value.new( + package_id => initialize_parameters.package_id, + parameter_id => cur_val.parameter_id, + attr_value => cur_val.default_value + ); + end loop; + end initialize_parameters; + + 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 + is + 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( + package_key => apm_package.new.package_key + ); + v_num_instances := apm_package.num_instances( + package_key => apm_package.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 = apm_package.new.package_key; + return v_package_id; + else + v_package_id := acs_object.new( + object_id => package_id, + object_type => object_type, + creation_date => creation_date, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => context_id + ); + if instance_name is null then + v_instance_name := package_key || ' ' || v_package_id; + else + v_instance_name := instance_name; + end if; + + select package_type into v_package_type + from apm_package_types + where package_key = apm_package.new.package_key; + + insert into apm_packages + (package_id, package_key, instance_name) + values + (v_package_id, 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; + + initialize_parameters( + package_id => v_package_id, + package_key => apm_package.new.package_key + ); + return v_package_id; + + end if; +end new; + + procedure delete ( + package_id in apm_packages.package_id%TYPE + ) + is + cursor all_values is + select value_id from apm_parameter_values + where package_id = apm_package.delete.package_id; + cursor all_site_nodes is + select node_id from site_nodes + where object_id = apm_package.delete.package_id; + begin + -- Delete all parameters. + for cur_val in all_values loop + apm_parameter_value.delete(value_id => cur_val.value_id); + end loop; + delete from apm_applications where application_id = apm_package.delete.package_id; + delete from apm_services where service_id = apm_package.delete.package_id; + delete from apm_packages where package_id = apm_package.delete.package_id; + -- Delete the site nodes for the objects. + for cur_val in all_site_nodes loop + site_node.delete(cur_val.node_id); + end loop; + -- Delete the object. + acs_object.delete ( + object_id => package_id + ); + end delete; + + function singleton_p ( + package_key in apm_packages.package_key%TYPE + ) return integer + is + 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'; + return v_singleton_p; + + exception + when NO_DATA_FOUND + then + return 0; + end singleton_p; + + function num_instances ( + package_key in apm_package_types.package_key%TYPE + ) return integer + is + v_num_instances integer; + begin + select count(*) into v_num_instances + from apm_packages + where package_key = num_instances.package_key; + return v_num_instances; + + exception + when NO_DATA_FOUND + then + return 0; + end num_instances; + + function name ( + package_id in apm_packages.package_id%TYPE + ) return varchar2 + is + 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 name; + + procedure enable ( + package_id in apm_packages.package_id%TYPE + ) + is + begin + update apm_packages + set enabled_p = 't' + where package_id = enable.package_id; + end enable; + + procedure disable ( + package_id in apm_packages.package_id%TYPE + ) + is + begin + update apm_packages + set enabled_p = 'f' + where package_id = disable.package_id; + end disable; + + function highest_version ( + package_key in apm_package_types.package_key%TYPE + ) return apm_package_versions.version_id%TYPE + is + 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; + return v_version_id; + exception + when NO_DATA_FOUND + then + return 0; + end highest_version; +end apm_package; +/ +show errors + + +create or replace package body 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 + is + v_version_id apm_package_versions.version_id%TYPE; + begin + if version_id is null then + select acs_object_id_seq.nextval + into v_version_id + from dual; + else + v_version_id := version_id; + end if; + v_version_id := acs_object.new( + object_id => v_version_id, + object_type => 'apm_package_version' + ); + 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, package_key, version_name, version_uri, + summary, description_format, description, + release_date, vendor, vendor_uri, + installed_p, data_model_loaded_p); + return v_version_id; + end new; + + procedure delete ( + version_id in apm_packages.package_id%TYPE + ) + is + begin + delete from apm_package_owners + where version_id = apm_package_version.delete.version_id; + + delete from apm_package_files + where version_id = apm_package_version.delete.version_id; + + delete from apm_package_dependencies + where version_id = apm_package_version.delete.version_id; + + delete from apm_package_versions + where version_id = apm_package_version.delete.version_id; + + acs_object.delete(apm_package_version.delete.version_id); + + end delete; + + procedure enable ( + version_id in apm_package_versions.version_id%TYPE + ) + is + begin + update apm_package_versions set enabled_p = 't' + where version_id = enable.version_id; + end enable; + + procedure disable ( + version_id in apm_package_versions.version_id%TYPE + ) + is + begin + update apm_package_versions + set enabled_p = 'f' + where version_id = disable.version_id; + end disable; + + + function copy( + version_id in apm_package_versions.version_id%TYPE, + new_version_id in apm_package_versions.version_id%TYPE default null, + new_version_name in apm_package_versions.version_name%TYPE, + new_version_uri in apm_package_versions.version_uri%TYPE + ) return apm_package_versions.version_id%TYPE + is + v_version_id integer; + begin + v_version_id := acs_object.new( + object_id => new_version_id, + object_type => 'apm_package_version' + ); + + 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 copy; + + 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 + is + v_version_id apm_package_versions.version_id%TYPE; + version_unchanged_p integer; + begin + -- Determine if version has changed. + select decode(count(*),0,0,1) 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 := copy( + version_id => edit.version_id, + new_version_id => edit.new_version_id, + new_version_name => edit.version_name, + new_version_uri => 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 = trunc(sysdate), + 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 edit; + + 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 + is + 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; + return v_file_id; + exception + when NO_DATA_FOUND + then + if file_id is null then + select acs_object_id_seq.nextval into v_file_id from dual; + else + v_file_id := 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); + return v_file_id; + end add_file; + + -- 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 + ) + is + begin + delete from apm_package_files + where version_id = remove_file.version_id + and path = remove_file.path; + end remove_file; + + +-- 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 + is + 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 add_interface; + + procedure remove_interface( + interface_id in apm_package_dependencies.dependency_id%TYPE + ) + is + begin + delete from apm_package_dependencies + where dependency_id = remove_interface.interface_id; + end remove_interface; + + 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 + ) + is + 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; + remove_interface(v_dep_id); + end remove_interface; + + -- 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 + is + 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 add_dependency; + + procedure remove_dependency( + dependency_id in apm_package_dependencies.dependency_id%TYPE + ) + is + begin + delete from apm_package_dependencies + where dependency_id = remove_dependency.dependency_id; + end remove_dependency; + + + 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 + ) + is + 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; + remove_dependency(v_dep_id); + end remove_dependency; + + function sortable_version_name ( + version_name in apm_package_versions.version_name%TYPE + ) return varchar2 + is + a_start integer; + a_end integer; + a_order varchar2(1000); + a_char char(1); + a_seen_letter char(1) := '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.'; + elsif a_char = 'a' then + a_order := a_order || ' 1A.'; + elsif a_char = 'b' then + a_order := a_order || ' 2B.'; + 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 sortable_version_name; + + 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 is + a_order_a varchar2(1000); + a_order_b varchar2(1000); + begin + a_order_a := sortable_version_name(version_name_one); + a_order_b := sortable_version_name(version_name_two); + if a_order_a < a_order_b then + return -1; + elsif a_order_a > a_order_b then + return 1; + end if; + return 0; + end version_name_greater; + + 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 + is + v_pos1 integer; + v_pos2 integer; + 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 := instr(v_path, '.', -1); + 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 version_name_greater(upgrade_p.initial_version_name, v_version_from) <= 0 and + 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 upgrade_p; + + procedure upgrade( + version_id in apm_package_versions.version_id%TYPE + ) + is + 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; + + end upgrade; + +end apm_package_version; +/ +show errors + +create or replace package body 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 + ) + is + 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); + end create_type; + + 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 + is + begin + UPDATE apm_package_types SET + pretty_name = nvl(update_type.pretty_name, pretty_name), + pretty_plural = nvl(update_type.pretty_plural, pretty_plural), + package_uri = nvl(update_type.package_uri, package_uri), + package_type = nvl(update_type.package_type, package_type), + spec_file_path = nvl(update_type.spec_file_path, spec_file_path), + spec_file_mtime = nvl(update_type.spec_file_mtime, spec_file_mtime), + singleton_p = nvl(update_type.singleton_p, singleton_p) + where package_key = update_type.package_key; + return update_type.package_key; + end update_type; + + procedure drop_type ( + package_key in apm_package_types.package_key%TYPE, + cascade_p in char default 'f' + ) + is + cursor all_package_ids is + select package_id + from apm_packages + where package_key = drop_type.package_key; + + cursor all_parameters is + select parameter_id from apm_parameters + where package_key = drop_type.package_key; + + cursor all_versions is + select version_id from apm_package_versions + where package_key = drop_type.package_key; + begin + if cascade_p = 't' then + for cur_val in all_package_ids + loop + apm_package.delete( + package_id => cur_val.package_id + ); + end loop; + -- Unregister all parameters. + for cur_val in all_parameters + loop + apm.unregister_parameter(parameter_id => cur_val.parameter_id); + end loop; + + -- Unregister all versions + for cur_val in all_versions + loop + apm_package_version.delete(version_id => cur_val.version_id); + end loop; + end if; + delete from apm_package_types + where package_key = drop_type.package_key; + end drop_type; + + function num_parameters ( + package_key in apm_package_types.package_key%TYPE + ) return integer + is + v_count integer; + begin + select count(*) into v_count + from apm_parameters + where package_key = num_parameters.package_key; + return v_count; + end num_parameters; + +end apm_package_type; + + +/ +show errors + +create or replace package body 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 + is + v_value_id apm_parameter_values.value_id%TYPE; + begin + v_value_id := acs_object.new( + object_id => value_id, + object_type => 'apm_parameter_value' + ); + insert into apm_parameter_values + (value_id, package_id, parameter_id, attr_value) + values + (v_value_id, apm_parameter_value.new.package_id, + apm_parameter_value.new.parameter_id, + apm_parameter_value.new.attr_value); + return v_value_id; + end new; + + procedure delete ( + value_id in apm_parameter_values.value_id%TYPE default null + ) + is + begin + delete from apm_parameter_values + where value_id = apm_parameter_value.delete.value_id; + acs_object.delete(value_id); + end delete; + + end apm_parameter_value; +/ +show errors; + +create or replace package body 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 + is + v_application_id integer; + begin + v_application_id := apm_package.new ( + package_id => application_id, + instance_name => instance_name, + package_key => package_key, + object_type => object_type, + creation_date => creation_date, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => context_id + ); + return v_application_id; + end new; + + procedure delete ( + application_id in acs_objects.object_id%TYPE + ) + is + begin + delete from apm_applications + where application_id = apm_application.delete.application_id; + apm_package.delete( + package_id => application_id); + end delete; + +end; +/ +show errors + +create or replace package body 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 + is + v_service_id integer; + begin + v_service_id := apm_package.new ( + package_id => service_id, + instance_name => instance_name, + package_key => package_key, + object_type => object_type, + creation_date => creation_date, + creation_user => creation_user, + creation_ip => creation_ip, + context_id => context_id + ); + return v_service_id; + end new; + + procedure delete ( + service_id in acs_objects.object_id%TYPE + ) + is + begin + delete from apm_services + where service_id = apm_service.delete.service_id; + apm_package.delete( + package_id => service_id + ); + end delete; + +end; +/ +show errors Index: openacs-4/packages/acs-kernel/sql/oracle/apm-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/apm-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/apm-drop.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,60 @@ +-- Uninstall file for the data model created by 'apm-create.sql' +-- +-- @author Bryan Quinn (bquinn) +-- @creation-date Mon Sep 18 16:46:56 2000 +-- +-- $Id: apm-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $ +-- + +drop package apm_service; +drop package apm_application; +drop package apm_parameter_value; +drop package apm_package_type; +drop package apm_package_version; +drop package apm_package; +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 cascade constraints; +drop table apm_applications cascade constraints; +drop table apm_packages cascade constraints; +drop table apm_package_types cascade constraints; + +begin + acs_object_type.drop_type ( + object_type => 'apm_package' + ); + + acs_object_type.drop_type ( + object_type => 'apm_application' + ); + + acs_object_type.drop_type ( + object_type => 'apm_service' + ); + + acs_object_type.drop_type ( + object_type => 'apm_package_version' + ); + + acs_object_type.drop_type ( + object_type => 'apm_parameter_value' + ); + + acs_object_type.drop_type ( + object_type => 'apm_parameter' + ); + commit; +end; +/ +show errors; Index: openacs-4/packages/acs-kernel/sql/oracle/community-core-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/community-core-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/community-core-create.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,675 @@ +-- +-- 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 $Id: community-core-create.sql,v 1.1 2001/03/20 22:51:55 donb 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 + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + -- + -- Party: the supertype of person and organization + -- + acs_object_type.create_type ( + supertype => 'acs_object', + object_type => 'party', + pretty_name => 'Party', + pretty_plural => 'Parties', + table_name => 'parties', + id_column => 'party_id', + package_name => 'party', + name_method => 'party.name' + ); + + attr_id := acs_attribute.create_attribute ( + object_type => 'party', + attribute_name => 'email', + datatype => 'string', + pretty_name => 'Email Address', + pretty_plural => 'Email Addresses', + min_n_values => 0, + max_n_values => 1 + ); + + attr_id := acs_attribute.create_attribute ( + object_type => 'party', + attribute_name => 'url', + datatype => 'string', + pretty_name => 'URL', + pretty_plural => 'URLs', + min_n_values => 0, + max_n_values => 1 + ); + + -- + -- Person: the supertype of user + -- + acs_object_type.create_type ( + supertype => 'party', + object_type => 'person', + pretty_name => 'Person', + pretty_plural => 'People', + table_name => 'persons', + id_column => 'person_id', + package_name => 'person', + name_method => 'person.name' + ); + + attr_id := acs_attribute.create_attribute ( + object_type => 'person', + attribute_name => 'first_names', + datatype => 'string', + pretty_name => 'First Names', + pretty_plural => 'First Names', + min_n_values => 0, + max_n_values => 1 + ); + + attr_id := acs_attribute.create_attribute ( + object_type => 'person', + attribute_name => 'last_name', + datatype => 'string', + pretty_name => 'Last Name', + pretty_plural => 'Last Names', + min_n_values => 0, + max_n_values => 1 + ); + + -- + -- User: people who have registered in the system + -- + acs_object_type.create_type ( + supertype => 'person', + object_type => 'user', + pretty_name => 'User', + pretty_plural => 'Users', + table_name => 'users', + id_column => 'user_id', + package_name => 'acs_user' + ); + + commit; +end; +/ +show errors + +-- ****************************************************************** +-- * OPERATIONAL LEVEL +-- ****************************************************************** + +create table parties ( + party_id not null + constraint parties_party_id_fk references + acs_objects (object_id) + constraint parties_pk primary key, + email varchar2(100) + constraint parties_email_un unique, + url varchar2(200) +); + +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 +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 + is + v_party_id parties.party_id%TYPE; + begin + v_party_id := + acs_object.new(party_id, object_type, + creation_date, creation_user, creation_ip, context_id); + + insert into parties + (party_id, email, url) + values + (v_party_id, lower(email), url); + + return v_party_id; + end new; + + procedure delete ( + party_id in parties.party_id%TYPE + ) + is + begin + acs_object.delete(party_id); + end delete; + + function name ( + party_id in parties.party_id%TYPE + ) + return varchar2 + is + begin + if party_id = -1 then + return 'The Public'; + else + return null; + end if; + end name; + +end party; +/ +show errors + +------------- +-- PERSONS -- +------------- + +create table persons ( + person_id not null + constraint persons_person_id_fk + references parties (party_id) + constraint persons_pk primary key, + first_names varchar2(100) not null, + last_name varchar2(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 +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 + is + v_person_id persons.person_id%TYPE; + begin + v_person_id := + party.new(person_id, object_type, + creation_date, creation_user, creation_ip, + email, url, context_id); + + insert into persons + (person_id, first_names, last_name) + values + (v_person_id, first_names, last_name); + + return v_person_id; + end new; + + procedure delete ( + person_id in persons.person_id%TYPE + ) + is + begin + delete from persons + where person_id = person.delete.person_id; + + party.delete(person_id); + end delete; + + function name ( + person_id in persons.person_id%TYPE + ) + return varchar2 + is + person_name varchar2(200); + begin + select first_names || ' ' || last_name + into person_name + from persons + where person_id = name.person_id; + + return person_name; + end name; + +end person; +/ +show errors + +create table users ( + user_id not null + constraint users_user_id_fk + references persons (person_id) + constraint users_pk primary key, + password char(40), + salt char(40), + screen_name varchar2(100) + constraint users_screen_name_un + unique, + priv_name integer default 0 not null, + priv_email integer default 5 not null, + email_verified_p char(1) default 't' + constraint users_email_verified_p_ck + check (email_verified_p in ('t', 'f')), + email_bouncing_p char(1) default 'f' not null + constraint users_email_bouncing_p_ck + check (email_bouncing_p in ('t','f')), + no_alerts_until date, + last_visit date, + second_to_last_visit date, + n_sessions integer default 1 not null, + password_question varchar2(1000), + password_answer varchar2(1000) +); + +create table user_preferences ( + user_id constraint user_prefs_user_id_fk + references users (user_id) + constraint user_preferences_pk + primary key, + prefer_text_only_p char(1) default 'f' + constraint user_prefs_pref_txt_only_p_ck + check (prefer_text_only_p in ('t','f')), + -- an ISO 639 language code (in lowercase) + language_preference char(2) default 'en', + dont_spam_me_p char(1) default 'f' + constraint user_prefs_dont_spam_me_p_ck + check (dont_spam_me_p in ('t','f')), + email_type varchar2(64) +); + +begin + + insert into acs_object_type_tables + (object_type, table_name, id_column) + values + ('user', 'user_preferences', 'user_id'); +end; +/ +show errors; + + +alter table acs_objects add ( + constraint acs_objects_creation_user_fk + foreign key (creation_user) references users(user_id), + 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 +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 + is + v_user_id users.user_id%TYPE; + begin + v_user_id := + person.new(user_id, object_type, + creation_date, creation_user, creation_ip, + email, url, + first_names, last_name, context_id); + + insert into users + (user_id, password, salt, password_question, password_answer, screen_name, + email_verified_p) + values + (v_user_id, password, salt, password_question, password_answer, screen_name, + email_verified_p); + + insert into user_preferences + (user_id) + values + (v_user_id); + + return v_user_id; + end new; + + function receives_alerts_p ( + user_id in users.user_id%TYPE + ) + return char + is + counter char(1); + begin + select decode(count(*),0,'f','t') into counter + from users + where no_alerts_until >= sysdate + and user_id = acs_user.receives_alerts_p.user_id; + + return counter; + + end receives_alerts_p; + + procedure approve_email ( + user_id in users.user_id%TYPE + ) + is + begin + update users + set email_verified_p = 't' + where user_id = approve_email.user_id; + end approve_email; + + + procedure unapprove_email ( + user_id in users.user_id%TYPE + ) + is + begin + update users + set email_verified_p = 'f' + where user_id = unapprove_email.user_id; + end unapprove_email; + + procedure delete ( + user_id in users.user_id%TYPE + ) + is + begin + delete from user_preferences + where user_id = acs_user.delete.user_id; + + delete from users + where user_id = acs_user.delete.user_id; + + person.delete(user_id); + end delete; + +end acs_user; +/ +show errors Index: openacs-4/packages/acs-kernel/sql/oracle/community-core-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/community-core-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/community-core-drop.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,25 @@ +-- +-- 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 $Id: community-core-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $ +-- + +-- We need to drop the circular creation_user and modifying_user +-- references before we can drop the users table. +-- +alter table acs_objects drop constraint acs_objects_creation_user_fk; +alter table acs_objects drop constraint acs_objects_modifying_user_fk; + +drop package acs_user; +drop table user_preferences; +drop table users; + +drop package person; +drop table persons; + +drop package party; +drop table parties; Index: openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/groups-body-create.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,749 @@ +-- +-- packages/acs-kernel/sql/groups-body-create.sql +-- +-- @author rhs@mit.edu +-- @creation-date 2000-08-22 +-- @cvs-id $Id: groups-body-create.sql,v 1.1 2001/03/20 22:51:55 donb Exp $ +-- + +-------------- +-- TRIGGERS -- +-------------- + +create or replace trigger membership_rels_in_tr +after insert on membership_rels +for each row +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 varchar2(4000); +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_application_error(-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; +end; +/ +show errors + +create or replace trigger composition_rels_in_tr +after insert on composition_rels +for each row +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 varchar2(4000); +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_application_error(-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; + +end; +/ +show errors + +create or replace trigger membership_rels_del_tr +before delete on membership_rels +for each row +declare + v_error varchar2(4000); +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_application_error(-20000,v_error); + end if; + + delete from group_element_index + where rel_id = :old.rel_id; +end; +/ +show errors; + +-- +-- TO DO: See if this can be optimized now that the member and component +-- mapping tables have been combined +-- +create or replace trigger composition_rels_del_tr +before delete on composition_rels +for each row +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 varchar2(4000); +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_application_error(-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; +end; +/ +show errors + + +-------------------- +-- PACKAGE BODIES -- +-------------------- + +create or replace package body 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 + is + v_rel_id integer; + begin + v_rel_id := acs_rel.new ( + rel_id => rel_id, + rel_type => rel_type, + object_id_one => object_id_one, + object_id_two => object_id_two, + context_id => object_id_one, + creation_user => creation_user, + creation_ip => creation_ip + ); + + insert into composition_rels + (rel_id) + values + (v_rel_id); + + return v_rel_id; + end; + + procedure delete ( + rel_id in composition_rels.rel_id%TYPE + ) + is + begin + acs_rel.delete(rel_id); + end; + + function check_path_exists_p ( + component_id in groups.group_id%TYPE, + container_id in groups.group_id%TYPE + ) return char + is + 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 check_path_exists_p(row.parent_id, container_id) = 't' then + return 't'; + end if; + end loop; + + return 'f'; + end; + + function check_index ( + component_id in groups.group_id%TYPE, + container_id in groups.group_id%TYPE + ) return char + is + result char(1); + n_rows integer; + 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 = component_id) loop + + if check_path_exists_p(dc.container_id, + check_index.container_id) = 't' then + select decode(count(*),0,0,1) 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'; + acs_log.error('composition_rel.check_representation', + 'Row missing from group_component_index for (' || + 'group_id = ' || container_id || ', ' || + 'component_id = ' || 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 + 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 + from dual) loop + if (r1.container_id != check_index.container_id or + r2.component_id != check_index.component_id) and + check_index(r2.component_id, r1.container_id) = 'f' then + result := 'f'; + end if; + end loop; + end loop; + + return result; + end; + + function check_representation ( + rel_id in composition_rels.rel_id%TYPE + ) return char + is + container_id groups.group_id%TYPE; + component_id groups.group_id%TYPE; + result char(1); + begin + result := 't'; + + if acs_object.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 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 check_path_exists_p(row.component_id, row.group_id) = 'f' then + result := 'f'; + 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; + +end composition_rel; +/ +show errors + + + + +create or replace package body 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 + is + v_rel_id integer; + begin + v_rel_id := acs_rel.new ( + rel_id => rel_id, + rel_type => rel_type, + object_id_one => object_id_one, + object_id_two => object_id_two, + context_id => object_id_one, + creation_user => creation_user, + creation_ip => creation_ip + ); + + insert into membership_rels + (rel_id, member_state) + values + (v_rel_id, new.member_state); + + return v_rel_id; + end; + + procedure ban ( + rel_id in membership_rels.rel_id%TYPE + ) + is + begin + update membership_rels + set member_state = 'banned' + where rel_id = ban.rel_id; + end; + + procedure approve ( + rel_id in membership_rels.rel_id%TYPE + ) + is + begin + update membership_rels + set member_state = 'approved' + where rel_id = approve.rel_id; + end; + + procedure reject ( + rel_id in membership_rels.rel_id%TYPE + ) + is + begin + update membership_rels + set member_state = 'rejected' + where rel_id = reject.rel_id; + end; + + procedure unapprove ( + rel_id in membership_rels.rel_id%TYPE + ) + is + begin + update membership_rels + set member_state = 'needs approval' + where rel_id = unapprove.rel_id; + end; + + procedure deleted ( + rel_id in membership_rels.rel_id%TYPE + ) + is + begin + update membership_rels + set member_state = 'deleted' + where rel_id = deleted.rel_id; + end; + + procedure delete ( + rel_id in membership_rels.rel_id%TYPE + ) + is + begin + acs_rel.delete(rel_id); + end; + + function check_index ( + group_id in groups.group_id%TYPE, + member_id in parties.party_id%TYPE, + container_id in groups.group_id%TYPE + ) return char + is + result char(1); + n_rows integer; + 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'; + acs_log.error('membership_rel.check_representation', + 'Row missing from group_member_index: ' || + 'group_id = ' || group_id || ', ' || + 'member_id = ' || member_id || ', ' || + 'container_id = ' || 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 = group_id) loop + if check_index(row.container_id, member_id, container_id) = 'f' then + result := 'f'; + end if; + end loop; + + return result; + end; + + function check_representation ( + rel_id in membership_rels.rel_id%TYPE + ) return char + is + group_id groups.group_id%TYPE; + member_id parties.party_id%TYPE; + result char(1); + begin + result := 't'; + + if acs_object.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 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'; + 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; + +end membership_rel; +/ +show errors + + + +create or replace package body 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 + is + 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(group_id, object_type, creation_date, creation_user, + creation_ip, email, url, context_id); + + v_join_policy := join_policy; + + -- if join policy wasn't 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 = object_type; + + if v_group_type_exists_p = 1 then + select default_join_policy into v_join_policy + from group_types + where group_type = object_type; + else + v_join_policy := 'open'; + end if; + end if; + + insert into groups + (group_id, group_name, join_policy) + values + (v_group_id, 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 new; + + + procedure delete ( + group_id in groups.group_id%TYPE + ) + is + begin + + -- Delete all segments defined for this group + for row in (select segment_id + from rel_segments + where group_id = acs_group.delete.group_id) loop + + 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 = acs_group.delete.group_id + or r.object_id_two = acs_group.delete.group_id)) loop + execute immediate 'begin ' || row.package_name || '.delete(' || row.rel_id || '); end;'; + end loop; + + party.delete(group_id); + end delete; + + function name ( + group_id in groups.group_id%TYPE + ) + return varchar2 + is + group_name varchar2(200); + begin + select group_name + into group_name + from groups + where group_id = name.group_id; + + return group_name; + end name; + + function member_p ( + party_id in parties.party_id%TYPE + ) + return char + is + begin + -- TO DO: implement this for real + return 't'; + end member_p; + + function check_representation ( + group_id in groups.group_id%TYPE + ) return char + is + result char(1); + begin + result := 't'; + 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; + + acs_log.notice('acs_group.check_representation', + 'Done running check_representation on group ' || group_id); + return result; + end; + +end acs_group; +/ +show errors Index: openacs-4/packages/acs-kernel/sql/oracle/groups-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/groups-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-kernel/sql/oracle/groups-create.sql 20 Mar 2001 22:51:55 -0000 1.1 @@ -0,0 +1,484 @@ +-- +-- packages/acs-kernel/sql/groups-create.sql +-- +-- @author rhs@mit.edu +-- @creation-date 2000-08-22 +-- @cvs-id $Id: groups-create.sql,v 1.1 2001/03/20 22:51:55 donb 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 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 constraint membership_rel_rel_id_fk + references acs_rels (rel_id) + constraint membership_rel_rel_id_pk + primary key, + member_state varchar2(20) not null + constraint membership_rel_mem_ck + check (member_state in ('approved', 'needs approval', + 'banned', 'rejected', 'deleted')) +); + +declare + attr_id acs_attributes.attribute_id%TYPE; +begin + -- + -- Group: a composite party + -- + acs_object_type.create_type ( + supertype => 'party', + object_type => 'group', + pretty_name => 'Group', + pretty_plural => 'Groups', + table_name => 'groups', + id_column => 'group_id', + package_name => 'acs_group', + type_extension_table => 'group_types', + name_method => 'acs_group.name' + ); + + attr_id := acs_attribute.create_attribute ( + object_type => 'group', + attribute_name => 'group_name', + datatype => 'string', + pretty_name => 'Group name', + pretty_plural => 'Group names', + min_n_values => 1, + max_n_values => 1 + ); + + -- + -- Composition Relationship + -- + acs_rel_type.create_role ('composite', 'Composite', 'Composites'); + acs_rel_type.create_role('component', 'Component', 'Components'); + + acs_rel_type.create_type ( + rel_type => 'composition_rel', + pretty_name => 'Composition Relation', + pretty_plural => 'Composition Relationships', + table_name => 'composition_rels', + id_column => 'rel_id', + package_name => 'composition_rel', + object_type_one => 'group', role_one => 'composite', + min_n_rels_one => 0, max_n_rels_one => null, + object_type_two => 'group', role_two => 'component', + min_n_rels_two => 0, max_n_rels_two => null + ); + + -- + -- Membership Relationship + -- + acs_rel_type.create_role ('member', 'Member', 'Members'); + + acs_rel_type.create_type ( + rel_type => 'membership_rel', + pretty_name => 'Membership Relation', + pretty_plural => 'Membership Relationships', + table_name => 'membership_rels', + id_column => 'rel_id', + package_name => 'membership_rel', + object_type_one => 'group', + min_n_rels_one => 0, max_n_rels_one => null, + object_type_two => 'person', role_two => 'member', + min_n_rels_two => 0, max_n_rels_two => null + ); + + commit; +end; +/ +show errors + +create table group_types ( + group_type not null + constraint group_types_pk primary key + constraint group_types_obj_type_fk + references acs_object_types (object_type), + default_join_policy varchar2(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 not null + constraint groups_group_id_fk + references parties (party_id) + constraint groups_pk primary key, + group_name varchar2(100) not null, + join_policy varchar2(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 not null + constraint gtr_rel_type_fk + references acs_rel_types (rel_type) + on delete cascade, + group_type 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 not null + constraint group_rels_rel_type_fk + references acs_rel_types (rel_type) + on delete cascade, + group_id 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"
+
+create table group_element_index (
+ group_id not null
+ constraint group_element_index_grp_id_fk
+ references groups (group_id),
+ element_id not null
+ constraint group_element_index_elem_id_fk
+ references parties (party_id),
+ rel_id not null
+ constraint group_element_index_rel_id_fk
+ references acs_rels (rel_id),
+ container_id not null
+ constraint group_element_index_cont_id_fk
+ references groups (group_id),
+ rel_type not null
+ constraint group_elem_index_rel_type_fk
+ references acs_rel_types (rel_type),
+ ancestor_rel_type varchar2(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)
+) organization index;
+
+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 or replace view group_element_map
+as select group_id, element_id, rel_id, container_id,
+ rel_type, ancestor_rel_type
+ from group_element_index;
+
+create or replace 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 or replace 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 or replace 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 or replace 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 or replace view group_component_index as select * from group_component_map;
+create or replace view group_member_index as select * from group_member_map;
+
+
+---------------
+-- FUNCTIONS --
+---------------
+
+create or replace function group_contains_p (group_id integer, component_id integer, rel_id integer default null) return char
+is
+begin
+ if group_id = component_id then
+ return 't';
+ else
+ if 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_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_id, map.group_id) = 't' then
+ return 't';
+ end if;
+ end loop;
+ end if;
+
+ return 'f';
+ end if;
+end;
+/
+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 or replace trigger membership_rels_in_tr
+after insert on membership_rels
+declare
+begin
+ raise_application_error(-20000,'Insert to membership rels not yet supported');
+end;
+/
+show errors
+
+
+create or replace trigger composition_rels_in_tr
+after insert on composition_rels
+declare
+begin
+ raise_application_error(-20000,'Insert to membership rels not yet supported');
+end;
+/
+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/oracle/groups-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/groups-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/groups-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,26 @@
+-
+-- packages/acs-kernel/sql/groups-drop.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-08-22
+-- @cvs-id $Id: groups-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+drop package acs_group;
+drop function group_contains_p;
+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;
+drop package composition_rel;
+drop package membership_rel;
+drop table composition_rels;
+drop table membership_rels;
+drop table group_types;
Index: openacs-4/packages/acs-kernel/sql/oracle/journal-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/journal-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/journal-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,135 @@
+-- Data model to keep a journal of all actions on objects.
+--
+--
+-- @author Lars Pind (lars@pinds.com)
+-- @creation-date 2000-22-18
+-- @cvs-id $Id: journal-create.sql,v 1.1 2001/03/20 22:51:55 donb 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
+
+
+begin
+ acs_object_type.create_type(
+ object_type => 'journal_entry',
+ pretty_name => 'Journal Entry',
+ pretty_plural => 'Journal Entries',
+ table_name => 'journal_entries',
+ id_column => 'journal_id',
+ package_name => 'journal_entry'
+ );
+
+ -- XXX fill in all the attributes in later.
+end;
+/
+show errors
+
+create table journal_entries (
+ journal_id 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 varchar2(100),
+ action_pretty varchar2(4000),
+ msg varchar2(4000)
+);
+
+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
+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,
+ 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
+ is
+ v_journal_id journal_entries.journal_id%TYPE;
+ begin
+ v_journal_id := acs_object.new (
+ object_id => journal_id,
+ object_type => 'journal_entry',
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => object_id
+ );
+
+ insert into journal_entries (
+ journal_id, object_id, action, action_pretty, msg
+ ) values (
+ v_journal_id, object_id, action, action_pretty, msg
+ );
+
+ return v_journal_id;
+ end new;
+
+ procedure delete(
+ journal_id in journal_entries.journal_id%TYPE
+ )
+ is
+ begin
+ delete from journal_entries where journal_id = journal_entry.delete.journal_id;
+ acs_object.delete(journal_entry.delete.journal_id);
+ end delete;
+
+ procedure delete_for_object(
+ object_id in acs_objects.object_id%TYPE
+ )
+ is
+ cursor journal_cur is
+ select journal_id from journal_entries where object_id = delete_for_object.object_id;
+ begin
+ for journal_rec in journal_cur loop
+ journal_entry.delete(journal_rec.journal_id);
+ end loop;
+ end delete_for_object;
+
+end journal_entry;
+/
+show errors;
+
Index: openacs-4/packages/acs-kernel/sql/oracle/journal-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/journal-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/journal-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,20 @@
+--
+-- 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 $Id: journal-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+--
+
+begin
+ acs_object_type.drop_type(
+ object_type => 'journal_entry'
+ );
+end;
+/
+show errors
+
+drop package journal_entry;
+drop table journal_entries;
Index: openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-body-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-body-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-body-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,155 @@
+--
+-- /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 $Id: rel-constraints-body-create.sql,v 1.1 2001/03/20 22:51:55 donb 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 or replace package body rel_constraint
+as
+
+ function new (
+ 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
+ is
+ v_constraint_id rel_constraints.constraint_id%TYPE;
+ begin
+ v_constraint_id := acs_object.new (
+ object_id => constraint_id,
+ object_type => constraint_type,
+ context_id => context_id,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into rel_constraints
+ (constraint_id, constraint_name,
+ rel_segment, rel_side, required_rel_segment)
+ values
+ (v_constraint_id, new.constraint_name,
+ new.rel_segment, new.rel_side, new.required_rel_segment);
+
+ return v_constraint_id;
+ end;
+
+ procedure delete (
+ constraint_id in rel_constraints.constraint_id%TYPE
+ )
+ is
+ begin
+ acs_object.delete(constraint_id);
+ end;
+
+ function get_constraint_id (
+ 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
+ is
+ v_constraint_id rel_constraints.constraint_id%TYPE;
+ begin
+ select constraint_id into v_constraint_id
+ from rel_constraints
+ where rel_segment = get_constraint_id.rel_segment
+ and rel_side = get_constraint_id.rel_side
+ and required_rel_segment = get_constraint_id.required_rel_segment;
+
+ return v_constraint_id;
+
+ end;
+
+
+ function violation (
+ rel_id in acs_rels.rel_id%TYPE
+ ) return varchar
+ is
+ v_error varchar(4000);
+ begin
+
+ v_error := null;
+
+ for constraint_violated in
+ (select /*+ FIRST_ROWS*/ constraint_id, constraint_name
+ from rel_constraints_violated_one
+ where rel_id = rel_constraint.violation.rel_id
+ and rownum = 1) loop
+
+ v_error := v_error || 'Relational Constraint Violation: ' ||
+ constraint_violated.constraint_name ||
+ ' (constraint_id=' ||
+ constraint_violated.constraint_id || '). ';
+
+ return v_error;
+ end loop;
+
+ for constraint_violated in
+ (select /*+ FIRST_ROWS*/ constraint_id, constraint_name
+ from rel_constraints_violated_two
+ where rel_id = rel_constraint.violation.rel_id
+ and rownum = 1) loop
+
+ v_error := v_error || 'Relational Constraint Violation: ' ||
+ constraint_violated.constraint_name ||
+ ' (constraint_id=' ||
+ constraint_violated.constraint_id || '). ';
+
+ return v_error;
+ end loop;
+
+ return v_error;
+
+ end violation;
+
+ function violation_if_removed (
+ rel_id in acs_rels.rel_id%TYPE
+ ) return varchar
+ is
+ v_count integer;
+ v_error varchar(4000);
+ begin
+ v_error := null;
+
+ select count(*) into v_count
+ from dual
+ where exists (select 1 from rc_violations_by_removing_rel r where r.rel_id = violation_if_removed.rel_id);
+
+ if v_count > 0 then
+ -- some other relation depends on this one. Let's build up a string
+ -- of the constraints we are violating
+ for constraint_violated in (select constraint_id, constraint_name
+ from rc_violations_by_removing_rel r
+ where r.rel_id = violation_if_removed.rel_id) loop
+
+ v_error := v_error || 'Relational Constraint Violation: ' ||
+ constraint_violated.constraint_name ||
+ ' (constraint_id=' ||
+ constraint_violated.constraint_id || '). ';
+
+ end loop;
+
+ end if;
+
+ return v_error;
+
+ end;
+
+
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,489 @@
+--
+-- /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 $Id: rel-constraints-create.sql,v 1.1 2001/03/20 22:51:55 donb 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".
+--
+
+begin
+ acs_object_type.create_type(
+ object_type => 'rel_constraint',
+ pretty_name => 'Relational Constraint',
+ pretty_plural => 'Relational Constraints',
+ supertype => 'acs_object',
+ table_name => 'rel_constraints',
+ id_column => 'constraint_id',
+ package_name => 'rel_constraint'
+ );
+end;
+/
+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 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 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 or replace 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;
+
+
+-- 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 or replace 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;
+
+
+-- 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 or replace 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 or replace 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 or replace 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 or replace 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;
+
+
+-- 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 or replace 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;
+
+
+-- 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 or replace 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 or replace 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 or replace 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/oracle/rel-constraints-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/rel-constraints-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,21 @@
+--
+-- /packages/acs-kernel/sql/rel-constraints-drop.sql
+--
+-- @author Oumi Mehrotra
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: rel-constraints-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+
+
+begin
+acs_rel_type.drop_type('rel_constraint');
+end;
+/
+show errors
+
+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;
+drop package rel_constraint;
Index: openacs-4/packages/acs-kernel/sql/oracle/rel-segments-body-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/rel-segments-body-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/rel-segments-body-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,159 @@
+--
+-- packages/acs-kernel/sql/rel-segments-create.sql
+--
+-- @author Oumi Mehrotra oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: rel-segments-body-create.sql,v 1.1 2001/03/20 22:51:55 donb 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
+is
+ function new (
+ 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
+ is
+ v_segment_id rel_segments.segment_id%TYPE;
+ begin
+ v_segment_id :=
+ party.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 new;
+
+ procedure delete (
+ segment_id in rel_segments.segment_id%TYPE
+ )
+ is
+ begin
+
+ -- remove all constraints on this segment
+ for row in (select constraint_id
+ from rel_constraints
+ where rel_segment = rel_segment.delete.segment_id) loop
+
+ rel_constraint.delete(row.constraint_id);
+
+ end loop;
+
+ party.delete(segment_id);
+
+ end delete;
+
+ -- EXPERIMENTAL / UNSTABLE -- use at your own risk
+ --
+ function get (
+ group_id in rel_segments.group_id%TYPE,
+ rel_type in rel_segments.rel_type%TYPE
+ ) return rel_segments.segment_id%TYPE
+ is
+ 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 get;
+
+
+ -- 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.
+ function get_or_new (
+ 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
+ is
+ v_segment_id rel_segments.segment_id%TYPE;
+ v_segment_name rel_segments.segment_name%TYPE;
+ begin
+
+ v_segment_id := get(group_id, 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 (
+ object_type => 'rel_segment',
+ creation_user => null,
+ creation_ip => null,
+ email => null,
+ url => null,
+ segment_name => v_segment_name,
+ group_id => get_or_new.group_id,
+ rel_type => get_or_new.rel_type,
+ context_id => get_or_new.group_id
+ );
+
+ end if;
+
+ return v_segment_id;
+
+ end get_or_new;
+
+ function name (
+ segment_id in rel_segments.segment_id%TYPE
+ )
+ return rel_segments.segment_name%TYPE
+ is
+ segment_name varchar(200);
+ begin
+ select segment_name
+ into segment_name
+ from rel_segments
+ where segment_id = name.segment_id;
+
+ return segment_name;
+ end name;
+
+end rel_segment;
+/
+show errors
+
Index: openacs-4/packages/acs-kernel/sql/oracle/rel-segments-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/rel-segments-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/rel-segments-create.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,273 @@
+--
+-- packages/acs-kernel/sql/rel-segments-create.sql
+--
+-- @author Oumi Mehrotra oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: rel-segments-create.sql,v 1.1 2001/03/20 22:51:55 donb 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".
+--
+
+begin
+ --
+ -- Relational Segment: a dynamically derived set of parties, defined
+ -- in terms of a particular type of membership or
+ -- composition to a particular group.
+ --
+ acs_object_type.create_type (
+ supertype => 'party',
+ object_type => 'rel_segment',
+ pretty_name => 'Relational Party Segment',
+ pretty_plural => 'Relational Party Segments',
+ table_name => 'rel_segments',
+ id_column => 'segment_id',
+ package_name => 'rel_segment',
+ type_extension_table => 'rel_segment',
+ name_method => 'rel_segment.name'
+ );
+
+end;
+/
+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 not null
+ constraint rel_segments_segment_id_fk
+ references parties (party_id)
+ constraint rel_segments_pk primary key,
+ segment_name varchar2(230) not null,
+ group_id not null
+ constraint rel_segments_group_id_fk
+ references groups (group_id),
+ rel_type 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 or replace 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 or replace view rel_segment_distinct_party_map
+as select distinct segment_id, party_id, ancestor_rel_type
+ from rel_segment_party_map;
+
+create or replace 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';
+
+create or replace 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 or replace 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 or replace 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 or replace 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 or replace 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 or replace 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);
+
Index: openacs-4/packages/acs-kernel/sql/oracle/rel-segments-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/rel-segments-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/rel-segments-drop.sql 20 Mar 2001 22:51:55 -0000 1.1
@@ -0,0 +1,30 @@
+--
+-- packages/acs-kernel/sql/rel-segments-drop.sql
+--
+-- @author oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: rel-segments-drop.sql,v 1.1 2001/03/20 22:51:55 donb Exp $
+
+
+begin
+ for r in (select segment_id from rel_segments) loop
+ rel_segment.delete(r.segment_id);
+ end loop;
+
+ acs_object_type.drop_type('rel_segment');
+end;
+/
+show errors
+
+
+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;
+drop package rel_segment;
Index: openacs-4/packages/acs-kernel/sql/oracle/security-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/security-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/security-create.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,53 @@
+--
+-- /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 $Id: security-create.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+create table sec_session_properties (
+ session_id integer
+ constraint sec_session_prop_session_id_nn
+ not null,
+ module varchar2(50)
+ constraint sec_session_prop_module_nn
+ not null,
+ property_name varchar2(50)
+ constraint sec_session_prop_prop_name_nn
+ not null,
+ property_value varchar2(4000),
+ -- transmitted only across secure connections?
+ secure_p char(1)
+ constraint sec_session_prop_secure_p_ck
+ check(secure_p in ('t','f')),
+ last_hit integer
+ constraint sec_session_date_nn
+ not null,
+ primary key(session_id, module, property_name)
+) nologging storage (
+ initial 50m
+ next 50m
+ pctincrease 0)
+ parallel;
+
+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 date
+);
+
+create sequence sec_security_token_id_seq cache 100;
+
+-- 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 sec_id_seq cache 100 increment by 100;
Index: openacs-4/packages/acs-kernel/sql/oracle/security-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/security-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/security-drop.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,15 @@
+--
+-- /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 $Id: security-drop.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+drop sequence sec_id_seq;
+drop sequence 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/oracle/site-nodes-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/site-nodes-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/site-nodes-create.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,258 @@
+--
+-- packages/acs-kernel/sql/site-nodes-create.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-09-05
+-- @cvs-id $Id: site-nodes-create.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+begin
+ acs_object_type.create_type (
+ object_type => 'site_node',
+ pretty_name => 'Site Node',
+ pretty_plural => 'Site Nodes',
+ table_name => 'site_nodes',
+ id_column => 'node_id',
+ package_name => 'site_node'
+ );
+end;
+/
+show errors
+
+-- This table allows urls to be mapped to a node_ids.
+
+create table site_nodes (
+ node_id constraint site_nodes_node_id_fk
+ references acs_objects (object_id)
+ constraint site_nodes_node_id_pk
+ primary key,
+ parent_id constraint site_nodes_parent_id_fk
+ references site_nodes (node_id),
+ name varchar2(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 char(1) not null
+ constraint site_nodes_directory_p_ck
+ check (directory_p in ('t', 'f')),
+ -- Should urls that are logical children of this node be
+ -- mapped to this node?
+ pattern_p char(1) default 'f' not null
+ constraint site_nodes_pattern_p_ck
+ check (pattern_p in ('t', 'f')),
+ object_id 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
+as
+
+ 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
+ is
+ v_node_id site_nodes.node_id%TYPE;
+ v_directory_p site_nodes.directory_p%TYPE;
+ begin
+ if 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_application_error (
+ -20000,
+ 'Node ' || parent_id || ' is not a directory'
+ );
+ end if;
+ end if;
+
+ v_node_id := acs_object.new (
+ object_id => node_id,
+ object_type => 'site_node',
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ 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;
+
+ procedure delete (
+ node_id in site_nodes.node_id%TYPE
+ )
+ is
+ begin
+ delete from site_nodes
+ where node_id = site_node.delete.node_id;
+
+ acs_object.delete(node_id);
+ end;
+
+ function find_pattern (
+ node_id in site_nodes.node_id%TYPE
+ ) return site_nodes.node_id%TYPE
+ is
+ 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;
+ 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 node_id;
+ else
+ return find_pattern(v_parent_id);
+ end if;
+ end;
+
+ function node_id (
+ url in varchar2,
+ parent_id in site_nodes.node_id%TYPE default null
+ ) return site_nodes.node_id%TYPE
+ is
+ v_pos integer;
+ v_first site_nodes.name%TYPE;
+ v_rest varchar2(4000);
+ v_node_id integer;
+ v_pattern_p site_nodes.pattern_p%TYPE;
+ v_url varchar2(4000);
+ v_directory_p site_nodes.directory_p%TYPE;
+ v_trailing_slash_p char(1);
+ begin
+ v_url := 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 nvl(parent_id, 3.14) = nvl(site_node.node_id.parent_id, 3.14)
+ and nvl(name, chr(10)) = nvl(v_first, chr(10));
+ exception
+ when no_data_found then
+ return find_pattern(parent_id);
+ end;
+
+ if v_rest is null then
+ if v_trailing_slash_p = 't' and v_directory_p = 'f' then
+ return find_pattern(parent_id);
+ else
+ return v_node_id;
+ end if;
+ else
+ return node_id(v_rest, v_node_id);
+ end if;
+ end;
+
+ function url (
+ node_id in site_nodes.node_id%TYPE
+ ) return varchar2
+ is
+ v_parent_id site_nodes.node_id%TYPE;
+ v_name site_nodes.name%TYPE;
+ v_directory_p site_nodes.directory_p%TYPE;
+ begin
+ if 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 url(v_parent_id) || v_name || '/';
+ else
+ return url(v_parent_id) || v_name;
+ end if;
+ end;
+
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/site-nodes-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/site-nodes-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/site-nodes-drop.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,16 @@
+--
+-- packages/acs-kernel/sql/site-nodes-drop.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-09-06
+-- @cvs-id $Id: site-nodes-drop.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+drop package site_node;
+drop table site_nodes;
+
+begin
+ acs_object_type.drop_type ('site_node');
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/utilities-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/utilities-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/utilities-create.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,95 @@
+--
+-- /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 $Id: utilities-create.sql,v 1.1 2001/03/20 22:51:56 donb 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
+as
+ -- Retrieves v_count (not necessarily consecutive) nextval values from the
+ -- sequence named v_sequence_name.
+ function multiple_nextval(
+ v_sequence_name in varchar2,
+ v_count in integer
+ )
+ return varchar2
+ is
+ a_sequence_values varchar2(4000);
+ begin
+ execute immediate '
+ declare
+ a_nextval integer;
+ begin
+ for counter in 1..:v_count loop
+ select ' || v_sequence_name || '.nextval into a_nextval from dual;
+ :a_sequence_values := :a_sequence_values || '','' || a_nextval;
+ end loop;
+ end;
+ ' using in v_count, in out a_sequence_values;
+ return substr(a_sequence_values, 2);
+ end;
+
+ -- 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[]';
+
+ -- The hashing function can be changed to MD5 by using computeMD5.
+
+ function computehash (v_value IN varchar2)
+ return varchar2
+ as
+ v_hashed char(40);
+ begin
+ select RAWTOHEX(computehash_raw(v_value)) into v_hashed from dual;
+ return v_hashed;
+ end computehash;
+
+ function logical_negation (
+ true_or_false IN varchar2)
+ return varchar2
+ as
+ begin
+ IF true_or_false is null THEN
+ return null;
+ ELSIF true_or_false = 'f' THEN
+ return 't';
+ ELSE
+ return 'f';
+ END IF;
+ END logical_negation;
+
+end util;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/utilities-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/utilities-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/utilities-drop.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,11 @@
+--
+-- /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 $Id: utilities-drop.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+drop package util;
Index: openacs-4/packages/acs-kernel/sql/oracle/test/acs-objects-test.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test/acs-objects-test.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test/acs-objects-test.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,298 @@
+--
+-- acs-kernel/sql/acs-objects-test.sql
+--
+-- PL/SQL regression tests for the acs-objects system
+--
+-- Note: These tests use the utPLSQL regression package available at:
+-- ftp://ftp.oreilly.com/published/oreilly/oracle/utplsql/utplsql.zip
+--
+-- @author Richard Li (richardl@arsdigita.com)
+--
+-- @creation-date 19 September 2000
+--
+-- @cvs-id $Id: acs-objects-test.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+-- In order for utPLSQL to work, you need to grant
+-- specific permissions to your user:
+--
+-- grant create public synonym to servicename;
+-- grant drop public synonym to servicename;
+-- grant execute on dbms_pipe to servicename;
+-- grant drop any table to servicename;
+-- grant create any table to servicename;
+
+-- In order to execute the test, you need to set things up
+-- in your SQL*PLUS session. First type:
+--
+-- set serveroutput on size 1000000 format wrapped
+--
+-- Now, if you have the UTL_FILE PL/SQL package installed, type:
+--
+-- exec utplsql.setdir('/web/richard/packages/acs-kernel/sql');
+--
+-- Otherwise, you'll have to disable autocompilation and manually
+-- compile:
+--
+-- exec utplsql.autocompile (false);
+-- @acs-objects-test
+--
+-- To actually execute the test, type:
+--
+-- exec utplsql.test('acs_object');
+
+
+-- we need these here or else the PL/SQL won't compile.
+drop table ut_acs_objects;
+create table ut_acs_objects as select * from acs_objects;
+create table test_objects (test_id integer primary key, data varchar2(100));
+
+create or replace package ut#acs_object
+as
+
+ procedure setup;
+
+ procedure teardown;
+
+ procedure new;
+
+ procedure delete;
+
+ procedure name;
+
+ procedure default_name;
+
+ procedure set_attribute;
+
+ procedure get_attribute;
+
+end ut#acs_object;
+/
+show errors
+
+create or replace package body ut#acs_object
+as
+
+ procedure setup
+ is
+ attr_id acs_attributes.attribute_id%TYPE;
+ begin
+ teardown;
+ dbms_output.put_line('Setting up...');
+
+ -- create a copy of the table
+ execute immediate 'create table ut_acs_objects as
+ select * from acs_objects';
+
+ execute immediate 'create table test_objects (test_id integer primary key, data varchar2(100))';
+
+ -- create the test_object type
+ acs_object_type.create_type (
+ supertype => 'acs_object',
+ object_type => 'test_object',
+ pretty_name => 'Test Object',
+ pretty_plural => 'Test Objects',
+ table_name => 'test_objects',
+ id_column => 'test_id'
+ );
+
+ -- no API available for this yet
+ insert into acs_object_type_tables (object_type, table_name, id_column)
+ values ('test_object','test_objects','test_id');
+
+ -- create the attribute
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'test_object',
+ attribute_name => 'data',
+ pretty_name => 'Data',
+ pretty_plural => 'Mo Data',
+ datatype => 'string',
+ table_name => 'test_objects',
+ column_name => 'data'
+ );
+
+ utplsql.setpkg('acs_object');
+ utplsql.addtest('new');
+ utplsql.addtest('delete');
+ utplsql.addtest('name');
+ utplsql.addtest('default_name');
+ utplsql.addtest('set_attribute');
+ utplsql.addtest('get_attribute');
+ end;
+
+ procedure teardown
+ is
+ begin
+ dbms_output.put_line('Tearing down...');
+ -- delete the test object
+ delete from acs_attributes where object_type = 'test_object';
+ delete from acs_objects where object_type = 'test_object';
+ delete from acs_object_type_tables where object_type = 'test_object';
+
+ begin
+ execute immediate 'drop table test_objects';
+ exception
+ when others
+ then
+ null;
+ end;
+
+ -- clean out the test data
+ begin
+ execute immediate 'drop table ut_acs_objects';
+ exception
+ when others
+ then
+ null;
+ end;
+
+ -- delete the object_type
+ delete from acs_object_types where object_type = 'test_object';
+ end;
+
+ procedure new
+ is
+ begin
+ dbms_output.put_line('Testing new...');
+ -- Tests just the common functionality of the API.
+
+ utassert.eq (
+ msg_in => 'Creating a new test object',
+ check_this_in => acs_object.new(object_id => -1000, object_type => 'test_object'),
+ against_this_in => -1000
+ );
+
+ -- create an object
+ insert into ut_acs_objects(object_id, object_type, creation_date, security_inherit_p, last_modified)
+ values(-1000, 'test_object', sysdate, 't', sysdate);
+
+ -- Verify that the API does the correct insert.
+ utassert.eqtable (
+ msg_in => 'Comparing created data for object',
+ check_this_in => 'acs_objects',
+ against_this_in => 'ut_acs_objects'
+ );
+
+ utresult.show;
+
+ end;
+
+ procedure delete
+ is
+ begin
+ dbms_output.put_line('Testing delete...');
+
+ -- create a new object to delete; note that this test assumes that
+ -- the .new operator works.
+ utassert.eq (
+ msg_in => 'Creating a new test object',
+ check_this_in => acs_object.new(object_id => -1001, object_type => 'test_object'),
+ against_this_in => -1001
+ );
+
+ -- delete the row.
+ acs_object.delete(object_id => -1001);
+
+ -- verify object not there.
+ utassert.eqtable (
+ msg_in => 'Delete verification',
+ check_this_in => 'acs_objects',
+ against_this_in => 'ut_acs_objects'
+ );
+
+ utresult.show;
+
+ end;
+
+ procedure name
+ is
+ begin
+ dbms_output.put_line('Testing name...');
+
+ utassert.eq (
+ msg_in => 'Creating a name',
+ check_this_in => acs_object.name(object_id => -1000),
+ against_this_in => 'Test Object -1000'
+ );
+
+ utresult.show;
+
+ end;
+
+ procedure default_name
+ is
+ begin
+ dbms_output.put_line('Testing default_name...');
+
+ utassert.eq (
+ msg_in => 'Creating a name',
+ check_this_in => acs_object.default_name(object_id => -1000),
+ against_this_in => 'Test Object -1000'
+ );
+
+ utresult.show;
+
+ end;
+
+ procedure set_attribute
+ is
+ v_sql_result test_objects.data%TYPE;
+ begin
+ dbms_output.put_line('Testing set_attribute');
+
+ utassert.eq (
+ msg_in => 'Creating a new test object',
+ check_this_in => acs_object.new(object_id => -1003, object_type => 'test_object'),
+ against_this_in => -1003
+ );
+
+ -- since we didn't create a test object new constructor
+ -- we're going to insert into attributes here.
+ insert into test_objects(test_id) values(-1003);
+
+ acs_object.set_attribute(object_id_in => -1003,
+ attribute_name_in => 'data',
+ value_in => '2702');
+
+ -- since utassert isn't powerful enough right now, we do this
+ -- comparison manually
+ select data into v_sql_result from test_objects where test_id = -1003;
+
+ if v_sql_result = 2702 then
+ dbms_output.put_line('SUCCESS: set_attribute');
+ else
+ dbms_output.put_line('Verifying attribute data FAILED');
+ end if;
+
+ utresult.show;
+
+ end;
+
+ procedure get_attribute
+ is
+ v_attr_value varchar2(4000);
+ begin
+ dbms_output.put_line('Testing get_attribute');
+
+ -- we assume that set attribute works. since i'm lazy
+ -- i'm going to recycle the -1003 object.
+ acs_object.set_attribute(object_id_in => -1003,
+ attribute_name_in => 'data',
+ value_in => 'sugarwen');
+
+ v_attr_value := acs_object.get_attribute(object_id_in => -1003,
+ attribute_name_in => 'data');
+
+ if v_attr_value = 'sugarwen' then
+ dbms_output.put_line('SUCCESS: get_attribute');
+ else
+ dbms_output.put_line('Verifying get attribute data FAILED');
+ end if;
+
+ utresult.show;
+
+ end;
+
+end ut#acs_object;
+/
+show errors
+
Index: openacs-4/packages/acs-kernel/sql/oracle/test/groups-test.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test/groups-test.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test/groups-test.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,119 @@
+--
+-- packages/acs-kernel/sql/test/groups-test.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-10-07
+-- @cvs-id $Id: groups-test.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+set serveroutput on
+
+declare
+ A integer;
+ B integer;
+ C integer;
+ D integer;
+ E integer;
+ F integer;
+ G integer;
+
+ joe integer;
+ jane integer;
+ bob integer;
+ betty integer;
+ jack integer;
+ jill integer;
+ sven integer;
+ stacy integer;
+
+ rel_id integer;
+begin
+ -- Create the test groups.
+ A := acs_group.new(group_name => 'A');
+ B := acs_group.new(group_name => 'B');
+ C := acs_group.new(group_name => 'C');
+ D := acs_group.new(group_name => 'D');
+ E := acs_group.new(group_name => 'E');
+ F := acs_group.new(group_name => 'F');
+ G := acs_group.new(group_name => 'G');
+
+ -- Create the test members.
+ joe := acs_user.new(email => 'joe@asdf.com',
+ first_names => 'Joe', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jane := acs_user.new(email => 'jane@asdf.com',
+ first_names => 'Jane', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ bob := acs_user.new(email => 'bob@asdf.com',
+ first_names => 'Bob', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ betty := acs_user.new(email => 'betty@asdf.com',
+ first_names => 'Betty', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jack := acs_user.new(email => 'jack@asdf.com',
+ first_names => 'Jack', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jill := acs_user.new(email => 'jill@asdf.com',
+ first_names => 'Jill', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ sven := acs_user.new(email => 'sven@asdf.com',
+ first_names => 'Sven', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ stacy := acs_user.new(email => 'stacy@asdf.com',
+ first_names => 'Stacy', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+
+ -- Make a couple of compositions.
+
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => B);
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => C);
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => D);
+
+ rel_id := composition_rel.new(object_id_one => E, object_id_two => A);
+ rel_id := composition_rel.new(object_id_one => F, object_id_two => A);
+ rel_id := composition_rel.new(object_id_one => G, object_id_two => A);
+
+ -- Make a couple of memberships.
+
+ rel_id := membership_rel.new(object_id_one => B, object_id_two => joe);
+ rel_id := membership_rel.new(object_id_one => B, object_id_two => jane);
+ rel_id := membership_rel.new(object_id_one => B, object_id_two => betty);
+ rel_id := membership_rel.new(object_id_one => A, object_id_two => bob);
+ rel_id := membership_rel.new(object_id_one => A, object_id_two => betty);
+ rel_id := membership_rel.new(object_id_one => E, object_id_two => betty);
+
+ delete from acs_logs;
+
+ for g in (select * from groups) loop
+ if acs_group.check_representation(g.group_id) = 'f' then
+ dbms_output.put_line('Group ' || g.group_name || ' (' || g.group_id ||
+ ') failed.');
+ end if;
+ end loop;
+
+ -- Remove the test groups.
+ acs_group.delete(G);
+ acs_group.delete(F);
+ acs_group.delete(E);
+ acs_group.delete(D);
+ acs_group.delete(C);
+ acs_group.delete(B);
+ acs_group.delete(A);
+
+ -- Remove the test members.
+ acs_user.delete(joe);
+ acs_user.delete(jane);
+ acs_user.delete(bob);
+ acs_user.delete(betty);
+ acs_user.delete(jack);
+ acs_user.delete(jill);
+ acs_user.delete(sven);
+ acs_user.delete(stacy);
+end;
+/
+show errors
+
+
+select log_level, log_key, message
+from acs_logs
+where log_key = 'error';
Index: openacs-4/packages/acs-kernel/sql/oracle/test/rel-constraints-test.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test/rel-constraints-test.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test/rel-constraints-test.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,318 @@
+--
+-- packages/acs-kernel/sql/test/rel-constraints-test.sql
+--
+-- @author oumi@arsdigita.com
+-- @creation-date 2000-12-02
+-- @cvs-id $Id: rel-constraints-test.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+set serveroutput on
+
+create or replace procedure rel_constraint_dump_views
+is
+begin
+
+ dbms_output.put_line(' ');
+ dbms_output.put_line('Contents of view ''rel_constraints_violated_one'':');
+
+ for r in (select * from rel_constraints_violated_one) loop
+ dbms_output.put_line(rpad(r.constraint_id, 10) ||
+ rpad(r.rel_id, 10) ||
+ rpad(acs_object.name(r.container_id), 20) ||
+ rpad(acs_object.name(r.party_id), 20));
+ end loop;
+
+
+ dbms_output.put_line(' ');
+ dbms_output.put_line('Contents of view ''rel_constraints_violated_two'':');
+
+ for r in (select * from rel_constraints_violated_two) loop
+ dbms_output.put_line(rpad(r.constraint_id, 10) ||
+ rpad(r.rel_id, 10) ||
+ rpad(acs_object.name(r.container_id), 20) ||
+ rpad(acs_object.name(r.party_id), 20));
+ end loop;
+
+end rel_constraint_dump_views;
+/
+show errors
+
+create or replace procedure rel_constraint_test_check (
+ rel_id integer,
+ expect_violation_p char
+)
+is
+ v_violation_msg varchar(4000);
+ v_violation_p char;
+ v_object_id_one integer;
+ v_object_id_two integer;
+ v_rel_type acs_rels.rel_type%TYPE;
+begin
+
+ v_violation_p := 'f';
+
+ v_violation_msg := rel_constraint.violation(rel_id);
+
+ if v_violation_msg is not null then
+ v_violation_p := 't';
+ end if;
+
+ if v_violation_p != expect_violation_p then
+
+ 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 = rel_constraint_test_check.rel_id;
+
+ acs_log.error('rel_constraint_test_check',
+ 'Relation ' || acs_object.name(rel_id) ||
+ ' (' || rel_id || ')' ||
+ ' failed (violation_p = ' || v_violation_p || '). ' ||
+ 'Rel info: type = ' || v_rel_type || ', object one = ' ||
+ acs_object.name(v_object_id_one) ||
+ ' (' || v_object_id_one || ')' || ', object two = ' ||
+ acs_object.name(v_object_id_two) ||
+ ' (' || v_object_id_two || ').');
+
+ dbms_output.put_line('Relation ' || acs_object.name(rel_id) ||
+ ' (' || rel_id || ')' ||
+ ' failed (violation_p = ' || v_violation_p || '). ' ||
+ 'Rel info: type = ' || v_rel_type || ', object one = ' ||
+ acs_object.name(v_object_id_one) ||
+ ' (' || v_object_id_one || ')' || ', object two = ' ||
+ acs_object.name(v_object_id_two) ||
+ ' (' || v_object_id_two || ').');
+
+ dbms_output.put_line('Violation Message:');
+ dbms_output.put_line(v_violation_msg);
+
+
+ end if;
+
+end rel_constraint_test_check;
+/
+show errors
+
+-- creates blah_member_rel and yippe_member_rel relationships
+@rel-segments-test-types-create.sql
+
+declare
+ A integer;
+ B integer;
+ C integer;
+ D integer;
+ E integer;
+ F integer;
+ G integer;
+
+ joe integer;
+ jane integer;
+ bob integer;
+ betty integer;
+ jack integer;
+ jill integer;
+ sven integer;
+ stacy integer;
+
+ reg_users integer;
+
+ rel_id integer;
+
+ side_one_constraint integer;
+ side_two_constraint integer;
+
+ v_count integer;
+
+begin
+ -- Create the test groups.
+ A := acs_group.new(group_name => 'A');
+ B := acs_group.new(group_name => 'B');
+ C := acs_group.new(group_name => 'C');
+ D := acs_group.new(group_name => 'D');
+ E := acs_group.new(group_name => 'E');
+ F := acs_group.new(group_name => 'F');
+ G := acs_group.new(group_name => 'G');
+
+ -- Create the test members.
+ joe := acs_user.new(email => 'joe@asdf.com',
+ first_names => 'Joe', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jane := acs_user.new(email => 'jane@asdf.com',
+ first_names => 'Jane', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ bob := acs_user.new(email => 'bob@asdf.com',
+ first_names => 'Bob', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ betty := acs_user.new(email => 'betty@asdf.com',
+ first_names => 'Betty', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jack := acs_user.new(email => 'jack@asdf.com',
+ first_names => 'Jack', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jill := acs_user.new(email => 'jill@asdf.com',
+ first_names => 'Jill', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ sven := acs_user.new(email => 'sven@asdf.com',
+ first_names => 'Sven', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ stacy := acs_user.new(email => 'stacy@asdf.com',
+ first_names => 'Stacy', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+
+ -- Make a couple of compositions.
+
+ reg_users := acs.magic_object_id('registered_users');
+
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => B);
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => C);
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => D);
+
+ rel_id := composition_rel.new(object_id_one => E, object_id_two => A);
+ rel_id := composition_rel.new(object_id_one => E, object_id_two => F);
+
+ rel_id := composition_rel.new(object_id_one=>reg_users, object_id_two=>E);
+ rel_id := composition_rel.new(object_id_one=>reg_users, object_id_two=>G);
+
+ -- define a few segments.
+
+ -- define a few relational constraints.
+
+ side_two_constraint := rel_constraint.new(
+ constraint_name => 'Yippe: side 2 must be a ''blah'' of A',
+ rel_segment => acs_rel_segment.get_or_new(reg_users, 'yippe_member_rel'),
+ rel_side => 'two',
+ required_rel_segment => acs_rel_segment.get_or_new(A,'blah_member_rel')
+ );
+
+ side_one_constraint := rel_constraint.new(
+ constraint_name => 'Yippe: side 1 must be a component of E',
+ rel_segment => acs_rel_segment.get_or_new(reg_users, 'yippe_member_rel'),
+ rel_side => 'one',
+ required_rel_segment => acs_rel_segment.get_or_new(E, 'composition_rel')
+ );
+
+
+ delete from acs_logs;
+
+
+ -- Make a couple of memberships.
+
+ -- LEGAL MEMBERSHIPS:
+
+ -- textbook case:
+ -- joe is a blah of A, and F is component of E, so its legal to make joe
+ -- a yippe of F.
+ rel_id := blah_member_rel.new(object_id_one => A, object_id_two => joe);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 'f');
+
+ rel_id := yippe_member_rel.new(object_id_one => F, object_id_two => joe);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 'f');
+
+ -- do constraints respect group hierarchy? If so, this will be legal:
+ rel_id := blah_member_rel.new(object_id_one => B, object_id_two => jane);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 'f');
+
+ rel_id := yippe_member_rel.new(object_id_one => F, object_id_two => jane);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 'f');
+
+ -- ILLEGAL MEMBERSHIPS:
+
+ -- G is not a component of F, therefore no one can be a yippe of G
+ -- This should violated 2 constraints (object one and object two are both
+ -- invalid).
+ rel_id := yippe_member_rel.new(object_id_one => G, object_id_two => bob);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 't');
+
+ -- betty is not a blah of A, therefore she cannot be a yippe of F.
+ rel_id := yippe_member_rel.new(object_id_one => F, object_id_two => betty);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 't');
+
+ -- make sven be a regular member of A. Sven cannot be a yippe of F.
+ rel_id := membership_rel.new(object_id_one => A, object_id_two => sven);
+ rel_id := yippe_member_rel.new(object_id_one => F, object_id_two => sven);
+
+ rel_constraint_test_check(rel_id => rel_id,
+ expect_violation_p => 't');
+
+ -- TEST THE VIEWS (there should be 4 violated constraints,
+ -- 1 side one violation and 3 side two violations.
+
+ select count(*) into v_count
+ from rel_constraints_violated_one;
+
+ if v_count != 1 then
+ dbms_output.put_line ('rel_constraints_violated_one should have 1 row.' ||
+ ' Found ' || v_count || ' rows.');
+ rel_constraint_dump_views;
+ end if;
+
+ select count(*) into v_count
+ from rel_constraints_violated_two;
+
+ if v_count != 3 then
+ dbms_output.put_line ('rel_constraints_violated_two should have 2 rows.' ||
+ ' Found ' || v_count || ' rows.');
+ rel_constraint_dump_views;
+ end if;
+
+
+ -- Remove the constraints
+ rel_constraint.delete(side_one_constraint);
+ rel_constraint.delete(side_two_constraint);
+
+ -- Remove the test memebership relations
+ for r in (select * from blah_member_rels) loop
+ blah_member_rel.delete(r.rel_id);
+ end loop;
+
+ for r in (select * from yippe_member_rels) loop
+ yippe_member_rel.delete(r.rel_id);
+ end loop;
+
+ -- Remove the test segments.
+ acs_rel_segment.delete(acs_rel_segment.get(A,'blah_member_rel'));
+ acs_rel_segment.delete(acs_rel_segment.get(E,'composition_rel'));
+ acs_rel_segment.delete(acs_rel_segment.get(reg_users,'yippe_member_rel'));
+
+ -- Remove the test groups.
+ acs_group.delete(G);
+ acs_group.delete(F);
+ acs_group.delete(E);
+ acs_group.delete(D);
+ acs_group.delete(C);
+ acs_group.delete(B);
+ acs_group.delete(A);
+
+ -- Remove the test members.
+ acs_user.delete(joe);
+ acs_user.delete(jane);
+ acs_user.delete(bob);
+ acs_user.delete(betty);
+ acs_user.delete(jack);
+ acs_user.delete(jill);
+ acs_user.delete(sven);
+ acs_user.delete(stacy);
+end;
+/
+show errors
+
+
+drop procedure rel_constraint_test_check;
+
+@rel-segments-test-types-drop.sql
+
+select log_level, log_key, message
+from acs_logs
+where log_key = 'error';
Index: openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test-types-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test-types-create.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test-types-create.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,177 @@
+begin
+ acs_rel_type.create_type (
+ supertype => 'membership_rel',
+ rel_type => 'blah_member_rel',
+ pretty_name => 'Blah Membership Relationship',
+ pretty_plural => 'Blah Membership Relationships',
+ table_name => 'blah_member_rels',
+ id_column => 'rel_id',
+ package_name => 'blah_member_rel',
+ object_type_one => 'group',
+ min_n_rels_one => 0, max_n_rels_one => null,
+ object_type_two => 'party', role_two => 'member',
+ min_n_rels_two => 0, max_n_rels_two => null
+ );
+
+
+ acs_rel_type.create_type (
+ supertype => 'membership_rel',
+ rel_type => 'yippe_member_rel',
+ pretty_name => 'Yippe Membership Relationship',
+ pretty_plural => 'Yippe Membership Relationships',
+ table_name => 'yippe_member_rels',
+ id_column => 'rel_id',
+ package_name => 'yippe_member_rel',
+ object_type_one => 'group',
+ min_n_rels_one => 0, max_n_rels_one => null,
+ object_type_two => 'party', role_two => 'member',
+ min_n_rels_two => 0, max_n_rels_two => null
+ );
+end;
+/
+show errors
+
+create table blah_member_rels (
+ rel_id constraint blah_member_rel_id_fk
+ references membership_rels (rel_id)
+ constraint blah_member_rel_pk
+ primary key
+);
+
+create table yippe_member_rels (
+ rel_id constraint yippe_member_rel_id_fk
+ references membership_rels (rel_id)
+ constraint yippe_member_rel_pk
+ primary key
+);
+
+
+create or replace package blah_member_rel
+is
+ function new (
+ rel_id in blah_member_rels.rel_id%TYPE
+ default null,
+ rel_type in acs_rels.rel_type%TYPE
+ default 'blah_member_rel',
+ object_id_one in groups.group_id%TYPE,
+ object_id_two in parties.party_id%TYPE
+ ) return blah_member_rels.rel_id%TYPE;
+
+ procedure delete (
+ rel_id in blah_member_rels.rel_id%TYPE
+ );
+end blah_member_rel;
+/
+show errors
+
+create or replace package body blah_member_rel
+is
+ function new (
+ rel_id in blah_member_rels.rel_id%TYPE
+ default null,
+ rel_type in acs_rels.rel_type%TYPE
+ default 'blah_member_rel',
+ object_id_one in groups.group_id%TYPE,
+ object_id_two in parties.party_id%TYPE
+ ) return blah_member_rels.rel_id%TYPE
+ is
+ v_rel_id blah_member_rels.rel_id%TYPE;
+ begin
+
+ v_rel_id := membership_rel.new(
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two
+ );
+
+
+ insert into blah_member_rels
+ (rel_id)
+ values
+ (v_rel_id);
+
+ return v_rel_id;
+
+ end new;
+
+ procedure delete (
+ rel_id in blah_member_rels.rel_id%TYPE
+ )
+ is
+ begin
+
+ delete from blah_member_rels where rel_id = rel_id;
+
+ membership_rel.delete(rel_id);
+
+ end delete;
+end blah_member_rel;
+/
+show errors
+
+
+
+create or replace package yippe_member_rel
+is
+ function new (
+ rel_id in yippe_member_rels.rel_id%TYPE
+ default null,
+ rel_type in acs_rels.rel_type%TYPE
+ default 'yippe_member_rel',
+ object_id_one in groups.group_id%TYPE,
+ object_id_two in parties.party_id%TYPE
+ ) return yippe_member_rels.rel_id%TYPE;
+
+ procedure delete (
+ rel_id in yippe_member_rels.rel_id%TYPE
+ );
+end yippe_member_rel;
+/
+show errors
+
+create or replace package body yippe_member_rel
+is
+ function new (
+ rel_id in yippe_member_rels.rel_id%TYPE
+ default null,
+ rel_type in acs_rels.rel_type%TYPE
+ default 'yippe_member_rel',
+ object_id_one in groups.group_id%TYPE,
+ object_id_two in parties.party_id%TYPE
+ ) return yippe_member_rels.rel_id%TYPE
+ is
+ v_rel_id yippe_member_rels.rel_id%TYPE;
+ begin
+
+ v_rel_id := membership_rel.new(
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two
+ );
+
+
+ insert into yippe_member_rels
+ (rel_id)
+ values
+ (v_rel_id);
+
+ return v_rel_id;
+
+ end new;
+
+ procedure delete (
+ rel_id in yippe_member_rels.rel_id%TYPE
+ )
+ is
+ begin
+
+ delete from yippe_member_rels where rel_id = rel_id;
+
+ membership_rel.delete(rel_id);
+
+ end delete;
+end yippe_member_rel;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test-types-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test-types-drop.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test-types-drop.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,16 @@
+
+drop package blah_member_rel;
+drop package yippe_member_rel;
+
+drop table blah_member_rels;
+drop table yippe_member_rels;
+
+begin
+
+ acs_rel_type.drop_type('blah_member_rel');
+
+ acs_rel_type.drop_type('yippe_member_rel');
+
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test/rel-segments-test.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,264 @@
+--
+-- packages/acs-kernel/sql/test/rel-segments-test.sql
+--
+-- @author oumi@arsdigita.com
+-- @creation-date 2000-12-01
+-- @cvs-id $Id: rel-segments-test.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+set serveroutput on
+
+-- creates blah_member_rel and yippe_member_rel relationships
+@rel-segments-test-types-create.sql
+
+
+create or replace function rel_segment_test_check (
+ segment_id integer,
+ party_id integer,
+ container_id integer
+) return char
+is
+ v_pass_p char(1);
+begin
+
+ select decode(count(*), 0, 'f', 't') into v_pass_p
+ from rel_segment_party_map
+ where segment_id = rel_segment_test_check.segment_id
+ and party_id = rel_segment_test_check.party_id
+ and container_id = rel_segment_test_check.container_id;
+
+ if v_pass_p = 'f' then
+
+ dbms_output.put_line('Row missing from rel_segment_party_map for' ||
+ ' segment ''' || acs_object.name(segment_id) ||
+ ''' (' || segment_id || ')' ||
+ ', party ''' || acs_object.name(party_id) ||
+ ''' (' || party_id || ')' ||
+ ', container ''' || acs_object.name(container_id) ||
+ ''' (' ||container_id || ')');
+
+ acs_log.error('rel_segment_test_check',
+ 'Row missing from rel_segment_party_map for' ||
+ ' segment ''' || acs_object.name(segment_id) ||
+ ''' (' || segment_id || ')' ||
+ ', party ''' || acs_object.name(party_id) ||
+ ''' (' || party_id || ')' ||
+ ', container ''' || acs_object.name(container_id) ||
+ ''' (' ||container_id || ')');
+ end if;
+
+
+ return v_pass_p;
+
+end;
+/
+show errors
+
+
+declare
+ A integer;
+ B integer;
+ C integer;
+ D integer;
+ E integer;
+ F integer;
+ G integer;
+
+ joe integer;
+ jane integer;
+ bob integer;
+ betty integer;
+ jack integer;
+ jill integer;
+ sven integer;
+ stacy integer;
+
+ seg_G_blahs integer;
+ seg_E_yippes integer;
+
+ rel_id integer;
+begin
+ -- Create the test groups.
+ A := acs_group.new(group_name => 'A');
+ B := acs_group.new(group_name => 'B');
+ C := acs_group.new(group_name => 'C');
+ D := acs_group.new(group_name => 'D');
+ E := acs_group.new(group_name => 'E');
+ F := acs_group.new(group_name => 'F');
+ G := acs_group.new(group_name => 'G');
+
+ -- Create the test members.
+ joe := acs_user.new(email => 'joe@asdf.com',
+ first_names => 'Joe', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jane := acs_user.new(email => 'jane@asdf.com',
+ first_names => 'Jane', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ bob := acs_user.new(email => 'bob@asdf.com',
+ first_names => 'Bob', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ betty := acs_user.new(email => 'betty@asdf.com',
+ first_names => 'Betty', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jack := acs_user.new(email => 'jack@asdf.com',
+ first_names => 'Jack', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ jill := acs_user.new(email => 'jill@asdf.com',
+ first_names => 'Jill', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ sven := acs_user.new(email => 'sven@asdf.com',
+ first_names => 'Sven', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+ stacy := acs_user.new(email => 'stacy@asdf.com',
+ first_names => 'Stacy', last_name => 'Smith',
+ password => 'assword', salt => 'p');
+
+ -- Make a couple of compositions.
+
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => B);
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => C);
+ rel_id := composition_rel.new(object_id_one => A, object_id_two => D);
+
+ rel_id := composition_rel.new(object_id_one => E, object_id_two => A);
+ rel_id := composition_rel.new(object_id_one => F, object_id_two => A);
+ rel_id := composition_rel.new(object_id_one => G, object_id_two => A);
+
+ -- Make a couple of memberships.
+
+ rel_id := blah_member_rel.new(object_id_one => B, object_id_two => joe);
+ rel_id := yippe_member_rel.new(object_id_one => B, object_id_two => jane);
+ rel_id := blah_member_rel.new(object_id_one => B, object_id_two => betty);
+ rel_id := yippe_member_rel.new(object_id_one => A, object_id_two => bob);
+ rel_id := blah_member_rel.new(object_id_one => A, object_id_two => betty);
+ rel_id := yippe_member_rel.new(object_id_one => E, object_id_two => betty);
+
+
+ -- define a few segments.
+
+ -- the segment of all parties that are blah members of G
+ seg_G_blahs := acs_rel_segment.new(segment_name => 'Blahs of Group G',
+ group_id => G,
+ rel_type => 'blah_member_rel');
+
+ -- the segment of all parties that are yippe members of E
+ seg_E_yippes := acs_rel_segment.new(segment_name => 'Yippes of Group E',
+ group_id => E,
+ rel_type => 'yippe_member_rel');
+
+
+ delete from acs_logs;
+
+
+-- group_element_index_dump;
+-- rel_segment_party_map_dump;
+
+
+
+ -- Expectations:
+ -- 1. seg_G_blahs should include joe and betty
+ -- 2. seg_E_yippes should include bob, and jane, betty
+
+ -- check: seg_G_blahs contains joe with container B
+ if rel_segment_test_check(seg_G_blahs, joe, B) = 'f' then
+ dbms_output.put_line('Segment ' || acs_object.name(seg_G_blahs) ||
+ '(' || seg_G_blahs || ') failed. Group_id = ' || G);
+ end if;
+
+ -- check: seg_G_blahs contains betty with container B
+ if rel_segment_test_check(seg_G_blahs, betty, B) = 'f' then
+ dbms_output.put_line('Segment ' || acs_object.name(seg_G_blahs) ||
+ '(' || seg_G_blahs || ') failed. Group_id = ' || G);
+ end if;
+
+ -- check: seg_G_blahs contains betty with container A
+ if rel_segment_test_check(seg_G_blahs, betty, A) = 'f' then
+ dbms_output.put_line('Segment ' || acs_object.name(seg_G_blahs) ||
+ '(' || seg_G_blahs || ') failed. Group_id = ' || G);
+ end if;
+
+ -- check: seg_E_yippes contains jane with container B
+ if rel_segment_test_check(seg_E_yippes, jane, B) = 'f' then
+ dbms_output.put_line('Segment ' || acs_object.name(seg_E_yippes) ||
+ '(' || seg_E_yippes || ') failed. Group_id = ' || E);
+ end if;
+
+ -- check: seg_E_yippes contains bob with container A
+ if rel_segment_test_check(seg_E_yippes, bob, A) = 'f' then
+ dbms_output.put_line('Segment ' || acs_object.name(seg_E_yippes) ||
+ '(' || seg_E_yippes || ') failed. Group_id = ' || E);
+ end if;
+
+ -- check: seg_E_yippes contains betty with container E
+ if rel_segment_test_check(seg_E_yippes, betty, E) = 'f' then
+ dbms_output.put_line('Segment ' || acs_object.name(seg_E_yippes) ||
+ '(' || seg_E_yippes || ') failed. Group_id = ' || E);
+ end if;
+
+ -- Now we test on-the-fly creation of rel-segments with the get_or_new
+ -- function:
+
+ -- The segment of all memers of F should contain jane through group B
+ if rel_segment_test_check(
+ acs_rel_segment.get_or_new(F,'membership_rel'), jane, B) = 'f' then
+ dbms_output.put_line('Segment ' ||
+ acs_object.name(acs_rel_segment.get(F,'membership_rel')) ||
+ '(' || acs_rel_segment.get(F,'membership_rel')
+ || ') failed. Group_id = ' || F);
+ end if;
+
+ -- The segment of all memers of F should contain betty through group A
+ if rel_segment_test_check(
+ acs_rel_segment.get_or_new(F,'membership_rel'), betty, A) = 'f' then
+ dbms_output.put_line('Segment ' ||
+ acs_object.name(acs_rel_segment.get(F,'membership_rel')) ||
+ '(' || acs_rel_segment.get(F,'membership_rel')
+ || ') failed. Group_id = ' || A);
+ end if;
+
+
+
+ -- Remove the test segments.
+ acs_rel_segment.delete(seg_G_blahs);
+ acs_rel_segment.delete(seg_E_yippes);
+ acs_rel_segment.delete(acs_rel_segment.get(F,'membership_rel'));
+
+ -- Remove the test memebership relations
+ for r in (select * from blah_member_rels) loop
+ blah_member_rel.delete(r.rel_id);
+ end loop;
+
+ for r in (select * from yippe_member_rels) loop
+ yippe_member_rel.delete(r.rel_id);
+ end loop;
+
+
+ -- Remove the test groups.
+ acs_group.delete(G);
+ acs_group.delete(F);
+ acs_group.delete(E);
+ acs_group.delete(D);
+ acs_group.delete(C);
+ acs_group.delete(B);
+ acs_group.delete(A);
+
+ -- Remove the test members.
+ acs_user.delete(joe);
+ acs_user.delete(jane);
+ acs_user.delete(bob);
+ acs_user.delete(betty);
+ acs_user.delete(jack);
+ acs_user.delete(jill);
+ acs_user.delete(sven);
+ acs_user.delete(stacy);
+end;
+/
+show errors
+
+
+drop function rel_segment_test_check;
+
+@rel-segments-test-types-drop.sql
+
+select log_level, log_key, message
+from acs_logs
+where log_key = 'error';
Index: openacs-4/packages/acs-kernel/sql/oracle/test-harness/acs-core.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test-harness/acs-core.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test-harness/acs-core.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,35 @@
+--
+-- acs-core/sql/acs-core-test-harness.sql
+--
+-- Test harness for ACS Core's PL/SQL API
+--
+-- @author Michael Yoon (michael@arsdigita.com)
+--
+-- @creation-date 2000-08-05
+--
+-- @cvs-id $Id: acs-core.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+declare
+ uid users.user_id%TYPE;
+begin
+ dbms_output.put_line('Calling acs_user.new() to create user 1');
+
+ uid :=
+ acs_user.new(email => 'jane.doe@arsdigita.com',
+ first_names => 'Jane',
+ last_name => 'Doe',
+ password => 'janedoerules',
+ creation_ip => '127.0.0.1',
+ user_id => 1);
+
+ dbms_output.put_line('Calling acs_object.name() to get the name of user 1: ' || acs_object.name(1));
+
+ dbms_output.put_line('Calling acs_user.delete() to delete user 1');
+
+ acs_user.delete(1);
+end;
+/
+show errors
+
+
Index: openacs-4/packages/acs-kernel/sql/oracle/test-harness/acs-permissions.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/test-harness/acs-permissions.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/test-harness/acs-permissions.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,253 @@
+-- file: packages/acs-kernel/sql/acs-permissions-test.sql
+-- history: date email message
+-- 2000-08-10 rhs@mit.edu initial version
+
+begin
+ -- Objects for testing.
+ insert into acs_object_types
+ (object_type, supertype, pretty_name, pretty_plural)
+ values
+ ('bboard', 'acs_object', 'BBoard', 'BBoards');
+
+ insert into acs_object_types
+ (object_type, supertype, pretty_name, pretty_plural)
+ values
+ ('bboard_message', 'acs_object', 'BBoard Message', 'BBoard Messages');
+
+ --------------------------------------------------------------
+ -- Some privileges that will be fundamental to all objects. --
+ --------------------------------------------------------------
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('read');
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('write');
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('create');
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('delete');
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('admin');
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('all');
+
+ ----------------------------------------------------------
+ -- Some privileges that probably only apply to bboards. --
+ ----------------------------------------------------------
+
+ insert into acs_privileges
+ (privilege)
+ values
+ ('moderate');
+
+ -------------------------------------------------
+ -- Administrators can read, write, and create. --
+ -------------------------------------------------
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('admin', 'read');
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('admin', 'write');
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('admin', 'create');
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('admin', 'delete');
+
+ ------------------------------------
+ -- Moderators can read and write. --
+ ------------------------------------
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('moderate', 'read');
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('moderate', 'write');
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('all', 'admin');
+
+ insert into acs_privilege_hierarchy
+ (privilege, child_privilege)
+ values
+ ('all', 'moderate');
+
+ ------------------------
+ -- Methods on bboards --
+ ------------------------
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'select_any_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'update_any_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'delete_any_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'insert_bboard');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'update_bboard');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'select_bboard');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard', 'delete_bboard');
+
+ ---------------------------------
+ -- Methods on bboard messages. --
+ ---------------------------------
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard_message', 'select_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard_message', 'update_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard_message', 'insert_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard_message', 'delete_message');
+
+ insert into acs_methods
+ (object_type, method)
+ values
+ ('bboard_message', 'foo');
+
+ -------------------------------------------------------------------------
+ -- Mappings between privileges and methods on particular object types. --
+ -------------------------------------------------------------------------
+
+
+ -- Methods that correspond to read for a bboard
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('read', 'bboard', 'select_any_message');
+
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('read', 'bboard', 'select_bboard');
+
+ -- Methods that correspond to read for a bboard message.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('read', 'bboard_message', 'select_message');
+
+ -- Methods that correspond to write for a bboard.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('write', 'bboard', 'update_bboard');
+
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('write', 'bboard', 'update_any_message');
+
+ -- Methods that correspond to write for a bboard message.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('write', 'bboard_message', 'update_message');
+
+ -- Methods that correspond to create for a bboard.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('create', 'bboard', 'insert_bboard');
+
+ -- Methods that correspond to create for a bboard message.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('create', 'bboard_message', 'insert_message');
+
+ -- Methods that correspond to delete for a bboard.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('delete', 'bboard', 'delete_bboard');
+
+ -- Methods that correspond to delete for a bboard.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('delete', 'bboard', 'delete_any_message');
+
+ -- Methods that correspond to create for a bboard message.
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('delete', 'bboard_message', 'delete_message');
+
+ insert into acs_privilege_method_rules
+ (privilege, object_type, method)
+ values
+ ('all', 'bboard_message', 'foo');
+
+ commit;
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0-4.0.1.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0-4.0.1.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0-4.0.1.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,493 @@
+--
+-- /packages/acs-kernel/sql/upgrade/upgrade-4.0-4.0.1.sql
+--
+-- Upgrades ACS 4.0 to ACS 4.0.1
+--
+-- @author Multiple
+-- @creation-date Wed Nov 1 10:32:08 2000
+-- @cvs-id $Id: upgrade-4.0-4.0.1.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+-- upgrade security.
+
+create or replace package sec
+as
+
+ function allocate_sessions(
+ v_preallocated_server in varchar2,
+ v_sessions_to_allocate in integer
+ )
+ return varchar2;
+end sec;
+/
+show errors
+
+create or replace package body sec
+as
+
+ -- Insert a bunch of rows into sec_sessions with a given preallocated_server.
+ function allocate_sessions(
+ v_preallocated_server in varchar2,
+ v_sessions_to_allocate in integer
+ )
+ return varchar2
+ is
+ -- Define table types for bulk inserts.
+ type int_tab is table of integer index by binary_integer;
+
+ a_session_ids int_tab;
+ a_session_id_string varchar2(4000);
+
+ a_count integer := 1;
+ pragma autonomous_transaction;
+ begin
+ while a_count <= v_sessions_to_allocate loop
+ select sec_id_seq.nextval into a_session_ids(a_session_ids.count + 1) from dual;
+ a_session_id_string := a_session_id_string || ',' || a_session_ids(a_session_ids.count);
+ a_count := a_count + 1;
+ end loop;
+
+ forall i in 1..a_session_ids.count
+ insert into sec_sessions(session_id, preallocated_server)
+ values(a_session_ids(i), v_preallocated_server);
+
+ commit;
+
+ -- strip initial comma
+ return substr(a_session_id_string, 2);
+ end;
+end sec;
+/
+show errors
+
+drop table sec_browser_properties;
+drop table sec_login_tokens;
+
+alter table sec_sessions drop column token;
+alter table sec_sessions drop column secure_token;
+alter table sec_sessions drop column browser_id;
+alter table sec_sessions add (first_hit integer);
+update sec_sessions set first_hit = last_hit where last_hit is not null;
+alter table sec_sessions drop column last_hit;
+
+alter sequence sec_security_token_id_seq cache 100;
+alter sequence sec_id_seq cache 1000;
+
+create index sec_property_names on sec_session_properties(property_name);
+
+-- upgrade parties
+
+update parties set email = lower(email);
+
+-- performance improvements
+
+create bitmap index acs_obj_types_supertype_idx on acs_object_types (supertype);
+
+-- update apm procedures
+-- bquinn@arsdigita.com 11/18/2000
+
+declare
+ none_null_p integer;
+ cursor all_pretty_names is
+ select pretty_name from apm_package_types;
+begin
+ none_null_p := 1;
+ for cur_val in all_pretty_names
+ loop
+ if cur_val.pretty_name is not null then
+ none_null_p := 0;
+ end if;
+ end loop;
+ if none_null_p = 1 then
+ execute immediate 'alter table apm_package_types modify (pretty_name varchar2(100) not null)';
+ end if;
+end;
+/
+show errors
+
+create or replace package body 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
+ )
+ is
+ begin
+ apm_package_type.create_type(
+ package_key => register_package.package_key,
+ pretty_name => register_package.pretty_name,
+ pretty_plural => register_package.pretty_plural,
+ package_uri => register_package.package_uri,
+ package_type => register_package.package_type,
+ singleton_p => register_package.singleton_p,
+ spec_file_path => register_package.spec_file_path,
+ spec_file_mtime => spec_file_mtime
+ );
+ end register_package;
+
+ 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
+ is
+ begin
+
+ return apm_package_type.update_type(
+ package_key => update_package.package_key,
+ pretty_name => update_package.pretty_name,
+ pretty_plural => update_package.pretty_plural,
+ package_uri => update_package.package_uri,
+ package_type => update_package.package_type,
+ singleton_p => update_package.singleton_p,
+ spec_file_path => update_package.spec_file_path,
+ spec_file_mtime => update_package.spec_file_mtime
+ );
+
+ end update_package;
+
+
+ procedure unregister_package (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 't'
+ )
+ is
+ begin
+ apm_package_type.drop_type(
+ package_key => unregister_package.package_key,
+ cascade_p => unregister_package.cascade_p
+ );
+ end unregister_package;
+
+ function register_p (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_register_p integer;
+ begin
+ select decode(count(*),0,0,1) into v_register_p from apm_package_types
+ where package_key = register_p.package_key;
+ return v_register_p;
+ end register_p;
+
+ 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
+ )
+ is
+ begin
+ apm.register_package(
+ package_key => register_application.package_key,
+ pretty_name => register_application.pretty_name,
+ pretty_plural => register_application.pretty_plural,
+ package_uri => register_application.package_uri,
+ package_type => 'apm_application',
+ singleton_p => register_application.singleton_p,
+ spec_file_path => register_application.spec_file_path,
+ spec_file_mtime => register_application.spec_file_mtime
+ );
+ end register_application;
+
+ procedure unregister_application (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_application.package_key,
+ cascade_p => unregister_application.cascade_p
+ );
+ end unregister_application;
+
+ 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
+ )
+ is
+ begin
+ apm.register_package(
+ package_key => register_service.package_key,
+ pretty_name => register_service.pretty_name,
+ pretty_plural => register_service.pretty_plural,
+ package_uri => register_service.package_uri,
+ package_type => 'apm_service',
+ singleton_p => register_service.singleton_p,
+ spec_file_path => register_service.spec_file_path,
+ spec_file_mtime => register_service.spec_file_mtime
+ );
+ end register_service;
+
+ procedure unregister_service (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_service.package_key,
+ cascade_p => unregister_service.cascade_p
+ );
+ end unregister_service;
+
+ -- 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
+ is
+ v_parameter_id apm_parameters.parameter_id%TYPE;
+ cursor all_parameters is
+ select ap.package_id, p.parameter_id, p.default_value
+ from apm_parameters p, apm_parameter_values v, apm_packages ap
+ where p.package_key = ap.package_key
+ and p.parameter_id = v.parameter_id (+)
+ and v.attr_value is null
+ and p.package_key = register_parameter.package_key;
+ begin
+ -- Create the new parameter.
+ v_parameter_id := acs_object.new(
+ object_id => parameter_id,
+ object_type => 'apm_parameter'
+ );
+
+ 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, register_parameter.description,
+ register_parameter.package_key, register_parameter.datatype,
+ register_parameter.default_value, register_parameter.section_name,
+ register_parameter.min_n_values, register_parameter.max_n_values);
+ -- Propagate parameter to new instances.
+ for cur_val in all_parameters
+ loop
+ apm.set_value(
+ package_id => cur_val.package_id,
+ parameter_id => cur_val.parameter_id,
+ attr_value => cur_val.default_value
+ );
+ end loop;
+ return v_parameter_id;
+ end register_parameter;
+
+ 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
+ is
+ begin
+ update apm_parameters
+ set parameter_name = nvl(update_parameter.parameter_name, parameter_name),
+ default_value = nvl(update_parameter.default_value, default_value),
+ datatype = nvl(update_parameter.datatype, datatype),
+ description = nvl(update_parameter.description, description),
+ section_name = nvl(update_parameter.section_name, section_name),
+ min_n_values = nvl(update_parameter.min_n_values, min_n_values),
+ max_n_values = nvl(update_parameter.max_n_values, max_n_values)
+ where parameter_id = update_parameter.parameter_id;
+ return parameter_id;
+ end;
+
+ function parameter_p(
+ package_key in apm_package_types.package_key%TYPE,
+ parameter_name in apm_parameters.parameter_name%TYPE
+ ) return integer
+ is
+ v_parameter_p integer;
+ begin
+ select decode(count(*),0,0,1) 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 parameter_p;
+
+ procedure unregister_parameter (
+ parameter_id in apm_parameters.parameter_id%TYPE
+ default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where parameter_id = unregister_parameter.parameter_id;
+ delete from apm_parameters
+ where parameter_id = unregister_parameter.parameter_id;
+ acs_object.delete(parameter_id);
+ end unregister_parameter;
+
+ function id_for_name (
+ parameter_name in apm_parameters.parameter_name%TYPE,
+ package_key in apm_parameters.package_key%TYPE
+ ) return apm_parameters.parameter_id%TYPE
+ is
+ 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 id_for_name;
+
+ 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
+ is
+ 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 get_value;
+
+ 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
+ is
+ 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(
+ parameter_id => v_parameter_id,
+ package_id => get_value.package_id
+ );
+ end get_value;
+
+
+ -- 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
+ )
+ is
+ 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
+ when NO_DATA_FOUND
+ then
+ v_value_id := apm_parameter_value.new(
+ package_id => set_value.package_id,
+ parameter_id => set_value.parameter_id,
+ attr_value => set_value.attr_value
+ );
+ end set_value;
+
+ 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
+ )
+ is
+ 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);
+ apm.set_value(
+ parameter_id => v_parameter_id,
+ package_id => set_value.package_id,
+ attr_value => set_value.attr_value
+ );
+ exception
+ when NO_DATA_FOUND
+ then
+ RAISE_APPLICATION_ERROR(-20000, 'The specified package ' || set_value.package_id ||
+ ' does not exist in the system.');
+ end set_value;
+end apm;
+/
+show errors
+
+declare
+ file_type_p integer;
+begin
+ select decode(count(*), 0, 0, 1) into file_type_p from apm_package_file_types
+ where file_type_key = 'sqlj_code';
+ if file_type_p != 1 then
+ insert into apm_package_file_types(file_type_key, pretty_name) values('sqlj_code', 'SQLJ Library');
+ commit;
+ end if;
+end;
+/
+show errors
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0.1-4.1b.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0.1-4.1b.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0.1-4.1b.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,3796 @@
+--
+-- /packages/acs-kernel/sql/upgrade/upgrade-4.0.1-4.0.2.sql
+--
+-- Upgrades ACS Kernel 4.0.1 to ACS Kernel 4.0.2
+--
+-- @author Multiple
+-- @creation-date Wed Nov 1 10:32:08 2000
+-- @cvs-id $Id: upgrade-4.0.1-4.1b.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+-- security upgrade (richardl@arsdigita.com)
+
+alter table sec_sessions drop primary key cascade;
+alter table sec_session_properties add (last_hit integer);
+drop table sec_sessions;
+drop package sec;
+alter sequence sec_id_seq increment by 100;
+
+
+-- fixing two bugs in the package body.
+-- version.new now uses the v_version_id it constructs.
+-- The sortable_version_name procedure now fails gracefully.
+
+create or replace package body 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ begin
+ if version_id is null then
+ select acs_object_id_seq.nextval
+ into v_version_id
+ from dual;
+ else
+ v_version_id := version_id;
+ end if;
+ v_version_id := acs_object.new(
+ object_id => v_version_id,
+ object_type => 'apm_package_version'
+ );
+ 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, package_key, version_name, version_uri,
+ summary, description_format, description,
+ release_date, vendor, vendor_uri,
+ installed_p, data_model_loaded_p);
+ return v_version_id;
+ end new;
+
+ procedure delete (
+ version_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_owners
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_files
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_dependencies
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_versions
+ where version_id = apm_package_version.delete.version_id;
+
+ acs_object.delete(apm_package_version.delete.version_id);
+
+ end delete;
+
+ procedure enable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions set enabled_p = 't'
+ where version_id = enable.version_id;
+ end enable;
+
+ procedure disable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions
+ set enabled_p = 'f'
+ where version_id = disable.version_id;
+ end disable;
+
+
+ function copy(
+ version_id in apm_package_versions.version_id%TYPE,
+ new_version_id in apm_package_versions.version_id%TYPE default null,
+ new_version_name in apm_package_versions.version_name%TYPE,
+ new_version_uri in apm_package_versions.version_uri%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ v_version_id integer;
+ begin
+ v_version_id := acs_object.new(
+ object_id => new_version_id,
+ object_type => 'apm_package_version'
+ );
+
+ 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 copy;
+
+ 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ version_unchanged_p integer;
+ begin
+ -- Determine if version has changed.
+ select decode(count(*),0,0,1) 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 := copy(
+ version_id => edit.version_id,
+ new_version_id => edit.new_version_id,
+ new_version_name => edit.version_name,
+ new_version_uri => 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 = trunc(sysdate),
+ 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 edit;
+
+ 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
+ is
+ 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;
+ return v_file_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ if file_id is null then
+ select acs_object_id_seq.nextval into v_file_id from dual;
+ else
+ v_file_id := 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);
+ return v_file_id;
+ end add_file;
+
+ -- 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
+ )
+ is
+ begin
+ delete from apm_package_files
+ where version_id = remove_file.version_id
+ and path = remove_file.path;
+ end remove_file;
+
+
+-- 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
+ is
+ 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 add_interface;
+
+ procedure remove_interface(
+ interface_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_interface.interface_id;
+ end remove_interface;
+
+ 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
+ )
+ is
+ 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;
+ remove_interface(v_dep_id);
+ end remove_interface;
+
+ -- 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
+ is
+ 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 add_dependency;
+
+ procedure remove_dependency(
+ dependency_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_dependency.dependency_id;
+ end remove_dependency;
+
+
+ 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
+ )
+ is
+ 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;
+ remove_dependency(v_dep_id);
+ end remove_dependency;
+
+ function sortable_version_name (
+ version_name in apm_package_versions.version_name%TYPE
+ ) return varchar2
+ is
+ a_start integer;
+ a_end integer;
+ a_order varchar2(1000);
+ a_char char(1);
+ a_seen_letter char(1) := '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.';
+ elsif a_char = 'a' then
+ a_order := a_order || ' 1A.';
+ elsif a_char = 'b' then
+ a_order := a_order || ' 2B.';
+ 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 sortable_version_name;
+
+ 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 is
+ a_order_a varchar2(1000);
+ a_order_b varchar2(1000);
+ begin
+ a_order_a := sortable_version_name(version_name_one);
+ a_order_b := sortable_version_name(version_name_two);
+ if a_order_a < a_order_b then
+ return -1;
+ elsif a_order_a > a_order_b then
+ return 1;
+ end if;
+ return 0;
+ end version_name_greater;
+
+ 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
+ is
+ v_pos1 integer;
+ v_pos2 integer;
+ 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 := instr(v_path, '.', -1);
+ 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 version_name_greater(upgrade_p.initial_version_name, v_version_from) <= 0 and
+ 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 upgrade_p;
+
+ procedure upgrade(
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ 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;
+
+ end upgrade;
+
+end apm_package_version;
+/
+show errors
+
+
+--------------------------------------
+-- RELATIONAL SEGMENTATION UPGRADE
+-- oumi@arsdigita.com
+-- 1/5/2001
+--------------------------------------
+
+-- PATCH GROUPS SYSTEM based on changes to groups-create.sql
+
+-- combine group_member_index and group_component_index into
+-- group_element_index.
+
+
+create table group_element_index (
+ group_id not null
+ constraint group_element_index_grp_id_fk
+ references groups (group_id),
+ element_id not null
+ constraint group_element_index_elem_id_fk
+ references parties (party_id),
+ rel_id not null
+ constraint group_element_index_rel_id_fk
+ references acs_rels (rel_id),
+ container_id not null
+ constraint group_element_index_cont_id_fk
+ references groups (group_id),
+ rel_type not null
+ constraint group_elem_index_rel_type_fk
+ references acs_rel_types (rel_type),
+ ancestor_rel_type varchar2(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)
+) organization index;
+
+
+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.
+';
+
+-- populate with data from group_member_map and group_component_map
+
+insert into group_element_index
+(group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type)
+select gmm.group_id, gmm.member_id, gmm.rel_id, gmm.container_id,
+ acs_rels.rel_type, 'membership_rel' as ancestor_rel_type
+from group_member_map gmm,
+ acs_rels
+where gmm.rel_id = acs_rels.rel_id;
+
+insert into group_element_index
+(group_id, element_id, rel_id, container_id, rel_type, ancestor_rel_type)
+select gcm.group_id, gcm.component_id, gcm.rel_id, gcm.container_id,
+ acs_rels.rel_type, 'composition_rel' as ancestor_rel_type
+from group_component_map gcm,
+ acs_rels
+where gcm.rel_id = acs_rels.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);
+
+-- create wrapper view for the above table.
+
+create or replace view group_element_map
+as select group_id, element_id, rel_id, container_id,
+ rel_type, ancestor_rel_type
+ from group_element_index;
+
+
+-- Re-write the group_member_map and group_component_map views
+-- as wrappers around group_element_index.
+
+create or replace 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 or replace 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';
+
+
+
+-- replace function that queried directly on group_component_index
+
+create or replace function group_contains_p (group_id integer, component_id integer, rel_id integer default null) return char
+is
+begin
+ if group_id = component_id then
+ return 't';
+ else
+ if 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_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_id, map.group_id) = 't' then
+ return 't';
+ end if;
+ end loop;
+ end if;
+
+ return 'f';
+ end if;
+end;
+/
+show errors
+
+
+-- If we're really confident, then we can drop the group_member_index
+-- and group_component_index.
+drop table group_component_index;
+drop table group_member_index;
+
+-- Just in case someone is still querying the group_component_index and
+-- group_member_index directly, lets make them views.
+create or replace view group_component_index as select * from group_component_map;
+create or replace view group_member_index as select * from group_member_map;
+
+
+----------------------------
+-- CREATE REL SEGMENTS
+-- oumi@arsdigita.com
+-- 1/5/2001
+-- Corresponding ACS File: ../rel-segments-create.sql
+----------------------------
+--
+-- packages/acs-kernel/sql/rel-segments-create.sql
+--
+-- @author Oumi Mehrotra oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: upgrade-4.0.1-4.1b.sql,v 1.1 2001/03/20 22:51:56 donb 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".
+--
+
+begin
+ --
+ -- Relational Segment: a dynamically derived set of parties, defined
+ -- in terms of a particular type of membership or
+ -- composition to a particular group.
+ --
+ acs_object_type.create_type (
+ supertype => 'party',
+ object_type => 'rel_segment',
+ pretty_name => 'Relational Party Segment',
+ pretty_plural => 'Relational Party Segments',
+ table_name => 'rel_segments',
+ id_column => 'segment_id',
+ package_name => 'rel_segment',
+ type_extension_table => 'rel_segment',
+ name_method => 'rel_segment.name'
+ );
+
+end;
+/
+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 not null
+ constraint rel_segments_segment_id_fk
+ references parties (party_id)
+ constraint rel_segments_pk primary key,
+ segment_name varchar2(230) not null,
+ group_id not null
+ constraint rel_segments_group_id_fk
+ references groups (group_id),
+ rel_type 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 or replace 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,
+ (select ancestor_type, object_type
+ from acs_object_type_supertype_map
+ union
+ select object_type, object_type
+ from acs_object_types) otsm,
+ group_element_map gem
+ where rs.rel_type = otsm.ancestor_type
+ and otsm.object_type = gem.rel_type
+ and gem.group_id = rs.group_id;
+
+
+create or replace view rel_segment_distinct_party_map
+as select distinct segment_id, party_id, ancestor_rel_type
+ from rel_segment_party_map;
+
+create or replace 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';
+
+create or replace view rel_seg_approved_member_map
+as select rspm.segment_id, rspm.party_id as member_id, rspm.rel_id,
+ rspm.rel_type, rspm.group_id, rspm.container_id
+ from rel_segment_party_map rspm, membership_rels mr
+ where rspm.rel_id = mr.rel_id
+ and mr.member_state = 'approved';
+
+create or replace 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 or replace 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 or replace 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 or replace 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;
+
+
+
+
+
+----------------------------
+-- RELATIONAL CONSTRAINTS --
+-- oumi@arsdigita.com
+-- 1/5/2001
+-- Corresponding ACS File: ../rel-constraints-create
+----------------------------
+--
+-- /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 $Id: upgrade-4.0.1-4.1b.sql,v 1.1 2001/03/20 22:51:56 donb 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".
+--
+
+begin
+ acs_object_type.create_type(
+ object_type => 'rel_constraint',
+ pretty_name => 'Relational Constraint',
+ pretty_plural => 'Relational Constraints',
+ supertype => 'acs_object',
+ table_name => 'rel_constraints',
+ id_column => 'constraint_id',
+ package_name => 'rel_constraint'
+ );
+end;
+/
+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 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 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 or replace 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;
+
+-- 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 or replace 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;
+
+-- 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_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 or replace view rc_required_rel_segments as
+ select group_ancestor_map.group_id,
+ rel_segments.rel_type,
+ required_rel_segment
+ from (select component_id as group_id,
+ group_id as ancestor_group_id
+ from group_component_map
+ union
+ select group_id as component_group_id,
+ group_id as ancestor_group_id
+ from groups) group_ancestor_map,
+ rel_segments,
+ rel_constraints
+ where rel_segments.group_id = group_ancestor_map.ancestor_group_id
+ and rel_constraints.rel_segment = rel_segments.segment_id
+ and rel_constraints.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 or replace 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_party_combos.group_id,
+ group_rel_type_party_combos.rel_type,
+ parties.party_id
+from rc_required_rel_segments,
+ (select groups.group_id, acs_rel_types.rel_type
+ from groups, acs_rel_types) group_rel_type_party_combos,
+ parties
+where rc_required_rel_segments.group_id(+) = group_rel_type_party_combos.group_id
+ and rc_required_rel_segments.rel_type(+) = group_rel_type_party_combos.rel_type
+ and rc_required_rel_segments.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 waht 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.segment_rel_id = :rel_id
+--
+
+create or replace 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
+ 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 cons.rel_segment = map.segment_id
+ and cons.required_rel_segment = s.segment_id;
+
+
+
+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
+
+
+
+
+-----------------------------
+-- UPDATE ACS_OBJECT_TYPES AND ACS_REL_ROLES
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- add dynamic_p column to acs_object_types
+-- add pretty_name, pretty_plural to acs_rel_roles and setup defaults
+-----------------------------
+
+-- we need a flag to know if object types were created dynamically and
+-- can thus be administered through the web
+alter table acs_object_types add ( dynamic_p char(1) default 'f'
+ constraint acs_obj_types_dynamic_p_ck
+ check (dynamic_p in ('t', 'f')));
+
+
+
+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.
+';
+
+
+-- Roles need pretty names and the such. Note we add them separately
+-- in case one has already been added on an acs installation
+
+alter table acs_rel_roles add (
+ pretty_name varchar2(100)
+);
+
+alter table acs_rel_roles add (
+ pretty_plural varchar2(100)
+);
+
+-- do these two updates separately in case the installation we are upgrading
+-- has altered these two columns
+update acs_rel_roles set pretty_name='Member', pretty_plural='Members' where role='member';
+update acs_rel_roles set pretty_name='Composite', pretty_plural='Composites' where role='composite';
+update acs_rel_roles set pretty_name='Component', pretty_plural='Components' where role='component';
+
+update acs_rel_roles set pretty_name=role where pretty_name is null;
+update acs_rel_roles set pretty_plural=role where pretty_plural is null;
+
+alter table acs_rel_roles modify pretty_name not null;
+alter table acs_rel_roles modify pretty_plural not null;
+
+
+-----------------------------
+-- PACKAGE BODY PARTY --
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- fix delete to simply call acs_object.delete
+------------------------------
+
+create or replace package body 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
+ is
+ v_party_id parties.party_id%TYPE;
+ begin
+ v_party_id :=
+ acs_object.new(party_id, object_type,
+ creation_date, creation_user, creation_ip, context_id);
+
+ insert into parties
+ (party_id, email, url)
+ values
+ (v_party_id, lower(email), url);
+
+ return v_party_id;
+ end new;
+
+ procedure delete (
+ party_id in parties.party_id%TYPE
+ )
+ is
+ begin
+ acs_object.delete(party_id);
+ end delete;
+
+ function name (
+ party_id in parties.party_id%TYPE
+ )
+ return varchar2
+ is
+ begin
+ if party_id = -1 then
+ return 'The Public';
+ else
+ return null;
+ end if;
+ end name;
+
+end party;
+/
+show errors
+
+
+-----------------------------
+-- MODIFICATIONS TO GROUPS --
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- defined default and permissable relationship types for group
+-- types and groups
+-- NEW TABLES: group_type_rels, group_rels with defaults set for existing groups
+-----------------------------
+
+create table group_type_rels (
+ group_rel_type_id integer constraint gtr_group_rel_type_id_pk primary key,
+ rel_type not null
+ constraint gtr_rel_type_fk
+ references acs_rel_types (rel_type)
+ on delete cascade,
+ group_type 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.
+';
+
+
+-- 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');
+
+
+create table group_rels (
+ group_rel_id integer constraint group_rels_group_rel_id_pk primary key,
+ rel_type not null
+ constraint group_rels_rel_type_fk
+ references acs_rel_types (rel_type)
+ on delete cascade,
+ group_id 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.
+';
+
+
+-- insert defaults for all groups.
+BEGIN
+
+ for rel_types in (select rel_type from acs_rel_types where rel_type in ('membership_rel','composition_rel')) loop
+ for row in (select group_id from groups) loop
+ insert into group_rels
+ (group_rel_id, rel_type, group_id)
+ values
+ (acs_object_id_seq.nextval, rel_types.rel_type, row.group_id);
+ end loop;
+ end loop;
+
+END;
+/
+show errors
+
+-------------------------------
+-- ACS_OBJECT_ATTRIBUTE_VIEW
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+-------------------------------
+-- Create a view to show us all the attributes for one object,
+-- including attributes for each of its supertypes
+
+create or replace 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
+ 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;
+
+
+-----------------------------
+-- PACKAGE ACS_OBJECT_TYPE
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- Add a type->pretty_name lookup function
+-- Drop all attributes of an object type when dropping the object type
+-----------------------------
+
+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;
+
+end acs_object_type;
+/
+show errors
+
+
+
+create or replace package body acs_object_type
+is
+
+ 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,
+ 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
+ )
+ is
+ v_package_name acs_object_types.package_name%TYPE;
+ begin
+ -- XXX This is a hack for losers who haven't created packages yet.
+ if package_name is null then
+ v_package_name := object_type;
+ else
+ v_package_name := 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
+ (object_type, pretty_name, pretty_plural, supertype, table_name,
+ id_column, abstract_p, type_extension_table, v_package_name,
+ name_method);
+ end create_type;
+
+ procedure drop_type (
+ object_type in acs_object_types.object_type%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ cursor c_attributes (object_type IN varchar) is
+ select attribute_name from acs_attributes where object_type = object_type;
+ begin
+
+ -- drop all the attributes associated with this type
+ for row in c_attributes (drop_type.object_type) loop
+ 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;
+ end drop_type;
+
+
+ function pretty_name (
+ object_type in acs_object_types.object_type%TYPE
+ ) return acs_object_types.pretty_name%TYPE
+ is
+ 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 pretty_name;
+
+end acs_object_type;
+/
+show errors
+
+
+-----------------------------
+-- PACKAGE BODY ACS_ATTRIBUTE
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- Modified drop_attribute to delete all values from acs_enum_values
+-- when dropping an attribute
+-----------------------------
+
+create or replace package body acs_attribute
+is
+
+ 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
+ is
+ v_sort_order acs_attributes.sort_order%TYPE;
+ v_attribute_id acs_attributes.attribute_id%TYPE;
+ begin
+ if sort_order is null then
+ select nvl(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 := sort_order;
+ end if;
+
+ select acs_attribute_id_seq.nextval into v_attribute_id from dual;
+
+ 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, object_type, table_name, column_name, attribute_name,
+ pretty_name, pretty_plural, v_sort_order, datatype, default_value,
+ min_n_values, max_n_values, storage, static_p);
+
+ return v_attribute_id;
+ end create_attribute;
+
+ procedure drop_attribute (
+ object_type in varchar2,
+ attribute_name in varchar2
+ )
+ is
+ 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;
+ end drop_attribute;
+
+ 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
+ )
+ is
+ begin
+ insert into acs_attribute_descriptions
+ (object_type, attribute_name, description_key, description)
+ values
+ (add_description.object_type, add_description.attribute_name,
+ add_description.description_key, add_description.description);
+ end;
+
+ 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
+ )
+ is
+ 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;
+ end;
+
+end acs_attribute;
+/
+show errors
+
+
+-----------------------------
+-- PACKAGE ACS_REL_TYPE
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- Modified create_role to accept pretty_name and pretty_plural
+-- added role_pretty_name, role_pretty_plural functions
+-- Modified drop_type to call acs_object_type.drop_type
+-----------------------------
+
+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
+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
+ )
+ is
+ begin
+ insert into acs_rel_roles
+ (role, pretty_name, pretty_plural)
+ values
+ (create_role.role, nvl(create_role.pretty_name,create_role.role), nvl(create_role.pretty_plural,create_role.role));
+ end;
+
+ procedure drop_role (
+ role in acs_rel_roles.role%TYPE
+ )
+ is
+ begin
+ delete from acs_rel_roles
+ where role = drop_role.role;
+ end;
+
+ function role_pretty_name (
+ role in acs_rel_roles.role%TYPE
+ ) return acs_rel_roles.pretty_name%TYPE
+ is
+ 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 role_pretty_name;
+
+
+ function role_pretty_plural (
+ role in acs_rel_roles.role%TYPE
+ ) return acs_rel_roles.pretty_plural%TYPE
+ is
+ 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 role_pretty_plural;
+
+ 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
+ )
+ is
+ begin
+ acs_object_type.create_type(
+ object_type => rel_type,
+ pretty_name => pretty_name,
+ pretty_plural => pretty_plural,
+ supertype => supertype,
+ table_name => table_name,
+ id_column => id_column,
+ package_name => package_name,
+ abstract_p => abstract_p,
+ type_extension_table => type_extension_table,
+ name_method => 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);
+ end;
+
+ procedure drop_type (
+ rel_type in acs_rel_types.rel_type%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ -- XXX do cascade_p
+ delete from acs_rel_types
+ where rel_type = drop_type.rel_type;
+
+ acs_object_type.drop_type(drop_type.rel_type, drop_type.cascade_p);
+ end;
+
+end acs_rel_type;
+/
+show errors
+
+
+
+-----------------------------
+-- PACKAGE BODY ACS_REL
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- fixes the delete proc to not delete from acs_rels (handled by acs_object.delete)
+-----------------------------
+
+create or replace package body 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,
+ creation_ip in acs_objects.creation_ip%TYPE default null
+ ) return acs_rels.rel_id%TYPE
+ is
+ 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 (
+ object_id => rel_id,
+ object_type => rel_type,
+ context_id => context_id,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ 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;
+
+ procedure delete (
+ rel_id in acs_rels.rel_id%TYPE
+ )
+ is
+ begin
+ acs_object.delete(rel_id);
+ end;
+
+end;
+/
+show errors
+
+
+-----------------------------
+-- PACKAGE BODY COMPOSITION_REL
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- fixes the delete proc to not delete from composition_rels (handled by acs_object.delete)
+-----------------------------
+create or replace package body 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
+ is
+ v_rel_id integer;
+ begin
+ v_rel_id := acs_rel.new (
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two,
+ context_id => object_id_one,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into composition_rels
+ (rel_id)
+ values
+ (v_rel_id);
+
+ return v_rel_id;
+ end;
+
+ procedure delete (
+ rel_id in composition_rels.rel_id%TYPE
+ )
+ is
+ begin
+ acs_rel.delete(rel_id);
+ end;
+
+ function check_path_exists_p (
+ component_id in groups.group_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ 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 check_path_exists_p(row.parent_id, container_id) = 't' then
+ return 't';
+ end if;
+ end loop;
+
+ return 'f';
+ end;
+
+ function check_index (
+ component_id in groups.group_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ n_rows integer;
+ 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 = component_id) loop
+
+ if check_path_exists_p(dc.container_id,
+ check_index.container_id) = 't' then
+ select decode(count(*),0,0,1) 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';
+ acs_log.error('composition_rel.check_representation',
+ 'Row missing from group_component_index for (' ||
+ 'group_id = ' || container_id || ', ' ||
+ 'component_id = ' || 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
+ 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
+ from dual) loop
+ if (r1.container_id != check_index.container_id or
+ r2.component_id != check_index.component_id) and
+ check_index(r2.component_id, r1.container_id) = 'f' then
+ result := 'f';
+ end if;
+ end loop;
+ end loop;
+
+ return result;
+ end;
+
+ function check_representation (
+ rel_id in composition_rels.rel_id%TYPE
+ ) return char
+ is
+ container_id groups.group_id%TYPE;
+ component_id groups.group_id%TYPE;
+ result char(1);
+ begin
+ result := 't';
+
+ if acs_object.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 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 check_path_exists_p(row.component_id, row.group_id) = 'f' then
+ result := 'f';
+ 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;
+
+end composition_rel;
+/
+show errors
+
+
+
+-----------------------------
+-- PACKAGE BODY MEMBERSHIP_REL
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- fixes the delete proc to not delete from composition_rels (handled by acs_object.delete)
+-----------------------------
+
+create or replace package body 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 null,
+ 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
+ is
+ v_rel_id integer;
+ begin
+ v_rel_id := acs_rel.new (
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two,
+ context_id => object_id_one,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into membership_rels
+ (rel_id, member_state)
+ values
+ (v_rel_id, new.member_state);
+
+ return v_rel_id;
+ end;
+
+ procedure ban (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'banned'
+ where rel_id = ban.rel_id;
+ end;
+
+ procedure approve (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'approved'
+ where rel_id = approve.rel_id;
+ end;
+
+ procedure reject (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'rejected'
+ where rel_id = reject.rel_id;
+ end;
+
+ procedure unapprove (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = ''
+ where rel_id = unapprove.rel_id;
+ end;
+
+ procedure deleted (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'deleted'
+ where rel_id = deleted.rel_id;
+ end;
+
+ procedure delete (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ acs_rel.delete(rel_id);
+ end;
+
+ function check_index (
+ group_id in groups.group_id%TYPE,
+ member_id in parties.party_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ n_rows integer;
+ 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';
+ acs_log.error('membership_rel.check_representation',
+ 'Row missing from group_member_index: ' ||
+ 'group_id = ' || group_id || ', ' ||
+ 'member_id = ' || member_id || ', ' ||
+ 'container_id = ' || 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 = group_id) loop
+ if check_index(row.container_id, member_id, container_id) = 'f' then
+ result := 'f';
+ end if;
+ end loop;
+
+ return result;
+ end;
+
+ function check_representation (
+ rel_id in membership_rels.rel_id%TYPE
+ ) return char
+ is
+ group_id groups.group_id%TYPE;
+ member_id parties.party_id%TYPE;
+ result char(1);
+ begin
+ result := 't';
+
+ if acs_object.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 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';
+ 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;
+
+end membership_rel;
+/
+show errors
+
+
+
+-----------------------------
+-- PACKAGE BODY ACS_GROUP
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- changed delete proc to delete all relations of any type.
+-----------------------------
+
+create or replace package body 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,
+ context_id in acs_objects.context_id%TYPE default null
+ )
+ return groups.group_id%TYPE
+ is
+ v_group_id groups.group_id%TYPE;
+ begin
+ v_group_id :=
+ party.new(group_id, object_type, creation_date, creation_user,
+ creation_ip, email, url, context_id);
+
+ insert into groups
+ (group_id, group_name)
+ values
+ (v_group_id, group_name);
+
+ -- 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 new;
+
+
+ procedure delete (
+ group_id in groups.group_id%TYPE
+ )
+ is
+ begin
+
+ -- 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 = acs_group.delete.group_id
+ or r.object_id_two = acs_group.delete.group_id)) loop
+ execute immediate 'begin ' || row.package_name || '.delete(' || row.rel_id || '); end;';
+ end loop;
+
+ party.delete(group_id);
+ end delete;
+
+ function name (
+ group_id in groups.group_id%TYPE
+ )
+ return varchar2
+ is
+ group_name varchar(200);
+ begin
+ select group_name
+ into group_name
+ from groups
+ where group_id = name.group_id;
+
+ return group_name;
+ end name;
+
+ function member_p (
+ party_id in parties.party_id%TYPE
+ )
+ return char
+ is
+ begin
+ -- TO DO: implement this for real
+ return 't';
+ end member_p;
+
+ function check_representation (
+ group_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ begin
+ result := 't';
+ 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;
+
+ acs_log.notice('acs_group.check_representation',
+ 'Done running check_representation on group ' || group_id);
+ return result;
+ end;
+
+end acs_group;
+/
+show errors
+
+
+
+-----------------------------
+-- CREATE NEW ATTRIBUTES
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+--
+-- CHANGES
+-- creates additional attributes for group, party, and acs_object
+-----------------------------
+
+declare
+ attr_id acs_attributes.attribute_id%TYPE;
+begin
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'group',
+ attribute_name => 'group_name',
+ datatype => 'string',
+ pretty_name => 'Group name',
+ pretty_plural => 'Group names',
+ min_n_values => 1,
+ max_n_values => 1
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'party',
+ attribute_name => 'email',
+ datatype => 'string',
+ pretty_name => 'Email Address',
+ pretty_plural => 'Email Addresses',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'party',
+ attribute_name => 'url',
+ datatype => 'string',
+ pretty_name => 'URL',
+ pretty_plural => 'URLs',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'creation_user',
+ datatype => 'integer',
+ pretty_name => 'Creation user',
+ pretty_plural => 'Creation users',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'acs_object',
+ attribute_name => 'context_id',
+ datatype => 'integer',
+ pretty_name => 'Context ID',
+ pretty_plural => 'Context IDs',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+end;
+/
+show errors;
+commit;
+
+
+-----------------------------
+-- UPDATE VIEW acs_object_party_privilege_map
+-- mbryzek@arsdigita.com
+-- 1/8/2001
+--
+-- CHANGES
+-- looks at rel_segment_member_map also
+-----------------------------
+
+create or replace 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_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_segment_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;
+
+
+
+---------------------------------
+-- UPDATE PACKAGE ACS PERMISSION
+---------------------------------
+
+create or replace package body 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
+ )
+ as
+ begin
+ insert into acs_permissions
+ (object_id, grantee_id, privilege)
+ values
+ (object_id, grantee_id, privilege);
+ exception
+ when dup_val_on_index then
+ return;
+ end grant_permission;
+
+ procedure revoke_permission (
+ object_id acs_permissions.object_id%TYPE,
+ grantee_id acs_permissions.grantee_id%TYPE,
+ privilege acs_permissions.privilege%TYPE
+ )
+ as
+ begin
+ delete from acs_permissions
+ where object_id = revoke_permission.object_id
+ and grantee_id = revoke_permission.grantee_id
+ and privilege = revoke_permission.privilege;
+ end revoke_permission;
+
+ function permission_p (
+ object_id acs_objects.object_id%TYPE,
+ party_id parties.party_id%TYPE,
+ privilege acs_privileges.privilege%TYPE
+ ) return char
+ as
+ exists_p char(1);
+ 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 decode(count(*),0,'f','t') 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;
+
+end acs_permission;
+/
+show errors
+
+
+
+
+----------------------------------------
+-- CREATE VALIDATION TRIGGER ON ACS_RELS
+-- oumi@arsdigita.com
+-- 1/11/2001
+--
+-- CHANGES
+-- add a trigger: before insert or update
+-- on acs_rels, validate that the relation
+-- is between objects of the correct
+-- object type.
+-----------------------------
+
+create or replace trigger acs_rels_in_tr
+before insert or update on acs_rels
+for each row
+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;
+
+exception
+ when NO_DATA_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_application_error (-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;
+/
+show errors
+
+
+
+
+------------------------------------------------------------
+-- RECREATE GROUP TRIGGERS TO ENFORE RELATIONAL CONSTRAINTS
+-- oumi@arsdigita.com
+-- 1/11/2001
+--
+-- CHANGES
+-- Modify insert and delete triggers to first check for
+-- violations of relational constraint
+-- Replace triggers that insert into group_member_index and
+-- group_component_index, so that they insert into group_element_index.--
+-- Replace triggers that delete from group_member_index and
+-- group_component_index
+--
+-- Corresponding ACS File: ../groups-body-create.sql
+------------------------------------------------------------
+--
+-- packages/acs-kernel/sql/groups-body-create.sql
+--
+-- @author rhs@mit.edu
+-- @creation-date 2000-08-22
+-- @cvs-id $Id: upgrade-4.0.1-4.1b.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+--
+
+--------------
+-- TRIGGERS --
+--------------
+
+create or replace trigger membership_rels_in_tr
+after insert on membership_rels
+for each row
+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 varchar2(4000);
+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_application_error(-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;
+end;
+/
+show errors
+
+create or replace trigger composition_rels_in_tr
+after insert on composition_rels
+for each row
+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 varchar2(4000);
+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_application_error(-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;
+
+end;
+/
+show errors
+
+create or replace trigger membership_rels_del_tr
+before delete on membership_rels
+for each row
+declare
+ v_error varchar2(4000);
+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_application_error(-20000,v_error);
+ end if;
+
+ delete from group_element_index
+ where rel_id = :old.rel_id;
+end;
+/
+show errors;
+
+--
+-- TO DO: See if this can be optimized now that the member and component
+-- mapping tables have been combined
+--
+create or replace trigger composition_rels_del_tr
+before delete on composition_rels
+for each row
+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 varchar2(4000);
+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_application_error(-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;
+end;
+/
+show errors
+
+
+--------------------
+-- PACKAGE BODIES --
+--------------------
+
+create or replace package body 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
+ is
+ v_rel_id integer;
+ begin
+ v_rel_id := acs_rel.new (
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two,
+ context_id => object_id_one,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into composition_rels
+ (rel_id)
+ values
+ (v_rel_id);
+
+ return v_rel_id;
+ end;
+
+ procedure delete (
+ rel_id in composition_rels.rel_id%TYPE
+ )
+ is
+ begin
+ acs_rel.delete(rel_id);
+ end;
+
+ function check_path_exists_p (
+ component_id in groups.group_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ 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 check_path_exists_p(row.parent_id, container_id) = 't' then
+ return 't';
+ end if;
+ end loop;
+
+ return 'f';
+ end;
+
+ function check_index (
+ component_id in groups.group_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ n_rows integer;
+ 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 = component_id) loop
+
+ if check_path_exists_p(dc.container_id,
+ check_index.container_id) = 't' then
+ select decode(count(*),0,0,1) 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';
+ acs_log.error('composition_rel.check_representation',
+ 'Row missing from group_component_index for (' ||
+ 'group_id = ' || container_id || ', ' ||
+ 'component_id = ' || 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
+ 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
+ from dual) loop
+ if (r1.container_id != check_index.container_id or
+ r2.component_id != check_index.component_id) and
+ check_index(r2.component_id, r1.container_id) = 'f' then
+ result := 'f';
+ end if;
+ end loop;
+ end loop;
+
+ return result;
+ end;
+
+ function check_representation (
+ rel_id in composition_rels.rel_id%TYPE
+ ) return char
+ is
+ container_id groups.group_id%TYPE;
+ component_id groups.group_id%TYPE;
+ result char(1);
+ begin
+ result := 't';
+
+ if acs_object.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 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 check_path_exists_p(row.component_id, row.group_id) = 'f' then
+ result := 'f';
+ 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;
+
+end composition_rel;
+/
+show errors
+
+
+
+
+create or replace package body 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 null,
+ 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
+ is
+ v_rel_id integer;
+ begin
+ v_rel_id := acs_rel.new (
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two,
+ context_id => object_id_one,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into membership_rels
+ (rel_id, member_state)
+ values
+ (v_rel_id, new.member_state);
+
+ return v_rel_id;
+ end;
+
+ procedure ban (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'banned'
+ where rel_id = ban.rel_id;
+ end;
+
+ procedure approve (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'approved'
+ where rel_id = approve.rel_id;
+ end;
+
+ procedure reject (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'rejected'
+ where rel_id = reject.rel_id;
+ end;
+
+ procedure unapprove (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = ''
+ where rel_id = unapprove.rel_id;
+ end;
+
+ procedure deleted (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'deleted'
+ where rel_id = deleted.rel_id;
+ end;
+
+ procedure delete (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ acs_rel.delete(rel_id);
+ end;
+
+ function check_index (
+ group_id in groups.group_id%TYPE,
+ member_id in parties.party_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ n_rows integer;
+ 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';
+ acs_log.error('membership_rel.check_representation',
+ 'Row missing from group_member_index: ' ||
+ 'group_id = ' || group_id || ', ' ||
+ 'member_id = ' || member_id || ', ' ||
+ 'container_id = ' || 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 = group_id) loop
+ if check_index(row.container_id, member_id, container_id) = 'f' then
+ result := 'f';
+ end if;
+ end loop;
+
+ return result;
+ end;
+
+ function check_representation (
+ rel_id in membership_rels.rel_id%TYPE
+ ) return char
+ is
+ group_id groups.group_id%TYPE;
+ member_id parties.party_id%TYPE;
+ result char(1);
+ begin
+ result := 't';
+
+ if acs_object.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 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';
+ 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;
+
+end membership_rel;
+/
+show errors
+
+
+
+create or replace package body 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,
+ context_id in acs_objects.context_id%TYPE default null
+ )
+ return groups.group_id%TYPE
+ is
+ v_group_id groups.group_id%TYPE;
+ begin
+ v_group_id :=
+ party.new(group_id, object_type, creation_date, creation_user,
+ creation_ip, email, url, context_id);
+
+ insert into groups
+ (group_id, group_name)
+ values
+ (v_group_id, group_name);
+
+ -- 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 new;
+
+
+ procedure delete (
+ group_id in groups.group_id%TYPE
+ )
+ is
+ begin
+
+ -- Delete all segments defined for this group
+ for row in (select segment_id
+ from rel_segments
+ where group_id = acs_group.delete.group_id) loop
+
+ 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 = acs_group.delete.group_id
+ or r.object_id_two = acs_group.delete.group_id)) loop
+ execute immediate 'begin ' || row.package_name || '.delete(' || row.rel_id || '); end;';
+ end loop;
+
+ party.delete(group_id);
+ end delete;
+
+ function name (
+ group_id in groups.group_id%TYPE
+ )
+ return varchar2
+ is
+ group_name varchar(200);
+ begin
+ select group_name
+ into group_name
+ from groups
+ where group_id = name.group_id;
+
+ return group_name;
+ end name;
+
+ function member_p (
+ party_id in parties.party_id%TYPE
+ )
+ return char
+ is
+ begin
+ -- TO DO: implement this for real
+ return 't';
+ end member_p;
+
+ function check_representation (
+ group_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ begin
+ result := 't';
+ 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;
+
+ acs_log.notice('acs_group.check_representation',
+ 'Done running check_representation on group ' || group_id);
+ return result;
+ end;
+
+end acs_group;
+/
+show errors
+
+
+
+
+
+------------------------------------------------------------
+-- CREATE THE rel_segment package body
+-- oumi@arsdigita.com
+-- 1/11/2001
+--
+-- Corresponding ACS File: ../rel-segments-body-create.sql
+------------------------------------------------------------
+--
+-- packages/acs-kernel/sql/rel-segments-create.sql
+--
+-- @author Oumi Mehrotra oumi@arsdigita.com
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: upgrade-4.0.1-4.1b.sql,v 1.1 2001/03/20 22:51:56 donb 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
+is
+ function new (
+ 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
+ is
+ v_segment_id rel_segments.segment_id%TYPE;
+ begin
+ v_segment_id :=
+ party.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 new;
+
+ procedure delete (
+ segment_id in rel_segments.segment_id%TYPE
+ )
+ is
+ begin
+
+ -- remove all constraints on this segment
+ for row in (select constraint_id
+ from rel_constraints
+ where rel_segment = rel_segment.delete.segment_id) loop
+
+ rel_constraint.delete(row.constraint_id);
+
+ end loop;
+
+ party.delete(segment_id);
+
+ end delete;
+
+ -- EXPERIMENTAL / UNSTABLE -- use at your own risk
+ --
+ function get (
+ group_id in rel_segments.group_id%TYPE,
+ rel_type in rel_segments.rel_type%TYPE
+ ) return rel_segments.segment_id%TYPE
+ is
+ 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 get;
+
+
+ -- 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.
+ function get_or_new (
+ 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
+ is
+ v_segment_id rel_segments.segment_id%TYPE;
+ v_segment_name rel_segments.segment_name%TYPE;
+ begin
+
+ v_segment_id := get(group_id, 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 (
+ object_type => 'rel_segment',
+ creation_user => null,
+ creation_ip => null,
+ email => null,
+ url => null,
+ segment_name => v_segment_name,
+ group_id => get_or_new.group_id,
+ rel_type => get_or_new.rel_type,
+ context_id => get_or_new.group_id
+ );
+
+ end if;
+
+ return v_segment_id;
+
+ end get_or_new;
+
+ function name (
+ segment_id in rel_segments.segment_id%TYPE
+ )
+ return rel_segments.segment_name%TYPE
+ is
+ segment_name varchar(200);
+ begin
+ select segment_name
+ into segment_name
+ from rel_segments
+ where segment_id = name.segment_id;
+
+ return segment_name;
+ end name;
+
+end rel_segment;
+/
+show errors
+
+
+
+
+
+------------------------------------------------------------
+-- CREATE THE rel_constraint package body
+-- oumi@arsdigita.com
+-- 1/11/2001
+--
+-- Corresponding ACS File: ../rel-constraints-body-create.sql
+------------------------------------------------------------
+--
+-- /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 $Id: upgrade-4.0.1-4.1b.sql,v 1.1 2001/03/20 22:51:56 donb 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 or replace package body rel_constraint
+as
+
+ function new (
+ 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
+ is
+ v_constraint_id rel_constraints.constraint_id%TYPE;
+ begin
+ v_constraint_id := acs_object.new (
+ object_id => constraint_id,
+ object_type => constraint_type,
+ context_id => context_id,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into rel_constraints
+ (constraint_id, constraint_name,
+ rel_segment, rel_side, required_rel_segment)
+ values
+ (v_constraint_id, new.constraint_name,
+ new.rel_segment, new.rel_side, new.required_rel_segment);
+
+ return v_constraint_id;
+ end;
+
+ procedure delete (
+ constraint_id in rel_constraints.constraint_id%TYPE
+ )
+ is
+ begin
+ acs_object.delete(constraint_id);
+ end;
+
+ function get_constraint_id (
+ 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
+ is
+ v_constraint_id rel_constraints.constraint_id%TYPE;
+ begin
+ select constraint_id into v_constraint_id
+ from rel_constraints
+ where rel_segment = get_constraint_id.rel_segment
+ and rel_side = get_constraint_id.rel_side
+ and required_rel_segment = get_constraint_id.required_rel_segment;
+
+ return v_constraint_id;
+
+ end;
+
+
+ function violation (
+ rel_id in acs_rels.rel_id%TYPE
+ ) return varchar
+ is
+ v_error varchar(4000);
+ begin
+
+ v_error := null;
+
+ for constraint_violated in
+ (select /*+ FIRST_ROWS*/ constraint_id, constraint_name
+ from rel_constraints_violated_one
+ where rel_id = rel_constraint.violation.rel_id
+ and rownum = 1) loop
+
+ v_error := v_error || 'Relational Constraint Violation: ' ||
+ constraint_violated.constraint_name ||
+ ' (constraint_id=' ||
+ constraint_violated.constraint_id || '). ';
+
+ return v_error;
+ end loop;
+
+ for constraint_violated in
+ (select /*+ FIRST_ROWS*/ constraint_id, constraint_name
+ from rel_constraints_violated_two
+ where rel_id = rel_constraint.violation.rel_id
+ and rownum = 1) loop
+
+ v_error := v_error || 'Relational Constraint Violation: ' ||
+ constraint_violated.constraint_name ||
+ ' (constraint_id=' ||
+ constraint_violated.constraint_id || '). ';
+
+ return v_error;
+ end loop;
+
+ return v_error;
+
+ end violation;
+
+ function violation_if_removed (
+ rel_id in acs_rels.rel_id%TYPE
+ ) return varchar
+ is
+ v_count integer;
+ v_error varchar(4000);
+ begin
+ v_error := null;
+
+ select count(*) into v_count
+ from dual
+ where exists (select 1 from rc_violations_by_removing_rel r where r.rel_id = violation_if_removed.rel_id);
+
+ if v_count > 0 then
+ -- some other relation depends on this one. Let's build up a string
+ -- of the constraints we are violating
+ for constraint_violated in (select constraint_id, constraint_name
+ from rc_violations_by_removing_rel r
+ where r.rel_id = violation_if_removed.rel_id) loop
+
+ v_error := v_error || 'Relational Constraint Violation: ' ||
+ constraint_violated.constraint_name ||
+ ' (constraint_id=' ||
+ constraint_violated.constraint_id || '). ';
+
+ end loop;
+
+ end if;
+
+ return v_error;
+
+ end;
+
+
+end;
+/
+show errors
+
+
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0b2-4.0rc0.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0b2-4.0rc0.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0b2-4.0rc0.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,1942 @@
+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 nuke_user (
+ user_id in 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
+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
+ is
+ 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);
+
+ v_rel_id := membership_rel.new (
+ object_id_two => v_user_id,
+ object_id_one => acs.magic_object_id('registered_users'),
+ member_state => member_state);
+
+ acs_permission.grant_permission (
+ object_id => v_user_id,
+ grantee_id => v_user_id,
+ privilege => 'read'
+ );
+
+ acs_permission.grant_permission (
+ object_id => v_user_id,
+ grantee_id => v_user_id,
+ privilege => 'write'
+ );
+
+ return v_user_id;
+ end;
+
+ procedure nuke_user (
+ user_id in users.user_id%TYPE
+ )
+ is
+ begin
+ -- Delete all relationships.
+ for cur_val in (select m.rel_id from acs_rels r, membership_rels m
+ where r.rel_id = m.rel_id
+ and r.object_id_two = nuke_user.user_id)
+ loop
+ membership_rel.delete(cur_val.rel_id);
+ end loop;
+
+ -- Delete all permissions
+ for cur_val in (select object_id, grantee_id, privilege
+ from acs_permissions
+ where grantee_id = nuke_user.user_id)
+ loop
+ acs_permission.revoke_permission(
+ object_id => cur_val.object_id,
+ grantee_id => cur_val.grantee_id,
+ privilege => cur_val.privilege
+ );
+ end loop;
+
+ acs_user.delete(user_id);
+ end;
+
+ procedure remove_user (
+ user_id in users.user_id%TYPE
+ )
+ is
+ begin
+ delete from users
+ where user_id = remove_user.user_id;
+ end;
+
+ function magic_object_id (
+ name in acs_magic_objects.name%TYPE
+ ) return acs_objects.object_id%TYPE
+ is
+ 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 object_id;
+ end magic_object_id;
+
+end acs;
+/
+show errors
+
+declare
+ schema_user varchar2(100);
+ jobnum integer;
+begin
+ 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,
+ 'sysdate + 1'
+ );
+end;
+/
+show errors
+
+create or replace package apm
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE;
+
+ 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.
+ function 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
+ ) return apm_package_types.package_key%TYPE;
+
+ -- 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'
+ );
+
+ function 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
+ ) return apm_package_types.package_key%TYPE;
+
+ -- 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
+ function 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
+ ) return apm_package_types.package_type%TYPE;
+
+ 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
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE
+ is
+ begin
+ return apm_package_type.create_type(
+ package_key => register_package.package_key,
+ pretty_name => register_package.pretty_name,
+ pretty_plural => register_package.pretty_plural,
+ package_uri => register_package.package_uri,
+ package_type => register_package.package_type,
+ singleton_p => register_package.singleton_p,
+ spec_file_path => register_package.spec_file_path,
+ spec_file_mtime => spec_file_mtime
+ );
+ end register_package;
+
+ 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
+ is
+ begin
+
+ return apm_package_type.update_type(
+ package_key => update_package.package_key,
+ pretty_name => update_package.pretty_name,
+ pretty_plural => update_package.pretty_plural,
+ package_uri => update_package.package_uri,
+ package_type => update_package.package_type,
+ singleton_p => update_package.singleton_p,
+ spec_file_path => update_package.spec_file_path,
+ spec_file_mtime => update_package.spec_file_mtime
+ );
+
+ end update_package;
+
+
+ procedure unregister_package (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 't'
+ )
+ is
+ begin
+ apm_package_type.drop_type(
+ package_key => unregister_package.package_key,
+ cascade_p => unregister_package.cascade_p
+ );
+ end unregister_package;
+
+ function register_p (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_register_p integer;
+ begin
+ select decode(count(*),0,0,1) into v_register_p from apm_package_types
+ where package_key = register_p.package_key;
+ return v_register_p;
+ end register_p;
+
+ function 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
+ ) return apm_package_types.package_key%TYPE
+ is
+ begin
+ return apm.register_package(
+ package_key => register_application.package_key,
+ pretty_name => register_application.pretty_name,
+ pretty_plural => register_application.pretty_plural,
+ package_uri => register_application.package_uri,
+ package_type => 'apm_application',
+ singleton_p => register_application.singleton_p,
+ spec_file_path => register_application.spec_file_path,
+ spec_file_mtime => register_application.spec_file_mtime
+ );
+ end register_application;
+
+ procedure unregister_application (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_application.package_key,
+ cascade_p => unregister_application.cascade_p
+ );
+ end unregister_application;
+
+ function 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
+ ) return apm_package_types.package_key%TYPE
+ is
+ begin
+ return apm.register_package(
+ package_key => register_service.package_key,
+ pretty_name => register_service.pretty_name,
+ pretty_plural => register_service.pretty_plural,
+ package_uri => register_service.package_uri,
+ package_type => 'apm_service',
+ singleton_p => register_service.singleton_p,
+ spec_file_path => register_service.spec_file_path,
+ spec_file_mtime => register_service.spec_file_mtime
+ );
+ end register_service;
+
+ procedure unregister_service (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_service.package_key,
+ cascade_p => unregister_service.cascade_p
+ );
+ end unregister_service;
+
+ -- 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
+ is
+ v_parameter_id apm_parameters.parameter_id%TYPE;
+ begin
+
+ v_parameter_id := acs_object.new(
+ object_id => parameter_id,
+ object_type => 'apm_parameter'
+ );
+ 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, register_parameter.description,
+ register_parameter.package_key, register_parameter.datatype,
+ register_parameter.default_value, register_parameter.section_name,
+ register_parameter.min_n_values, register_parameter.max_n_values);
+
+ return v_parameter_id;
+ -- XXX: create an attribute using the metadata system.
+
+ end register_parameter;
+
+ 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
+ is
+ begin
+ update apm_parameters
+ set parameter_name = nvl(update_parameter.parameter_name, parameter_name),
+ default_value = nvl(update_parameter.default_value, default_value),
+ datatype = nvl(update_parameter.datatype, datatype),
+ description = nvl(update_parameter.description, description),
+ section_name = nvl(update_parameter.section_name, section_name),
+ min_n_values = nvl(update_parameter.min_n_values, min_n_values),
+ max_n_values = nvl(update_parameter.max_n_values, max_n_values)
+ where parameter_id = update_parameter.parameter_id;
+ return parameter_id;
+ end;
+
+ function parameter_p(
+ package_key in apm_package_types.package_key%TYPE,
+ parameter_name in apm_parameters.parameter_name%TYPE
+ ) return integer
+ is
+ v_parameter_p integer;
+ begin
+ select decode(count(*),0,0,1) 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 parameter_p;
+
+ procedure unregister_parameter (
+ parameter_id in apm_parameters.parameter_id%TYPE
+ default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where parameter_id = unregister_parameter.parameter_id;
+ delete from apm_parameters
+ where parameter_id = unregister_parameter.parameter_id;
+ acs_object.delete(parameter_id);
+ end unregister_parameter;
+
+ function id_for_name (
+ parameter_name in apm_parameters.parameter_name%TYPE,
+ package_key in apm_parameters.package_key%TYPE
+ ) return apm_parameters.parameter_id%TYPE
+ is
+ 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 id_for_name;
+
+ 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
+ is
+ 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 get_value;
+
+ 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
+ is
+ 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(
+ parameter_id => v_parameter_id,
+ package_id => get_value.package_id
+ );
+ end get_value;
+
+
+ -- 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
+ )
+ is
+ 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
+ when NO_DATA_FOUND
+ then
+ v_value_id := apm_parameter_value.new(
+ package_id => package_id,
+ parameter_id => parameter_id,
+ attr_value => attr_value
+ );
+ end set_value;
+
+ 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
+ )
+ is
+ 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);
+ apm.set_value(
+ parameter_id => v_parameter_id,
+ package_id => set_value.package_id,
+ attr_value => set_value.attr_value
+ );
+ end set_value;
+end apm;
+/
+show errors
+
+create or replace package body apm_package
+as
+ procedure initialize_parameters (
+ package_id in apm_packages.package_id%TYPE,
+ package_key in apm_package_types.package_key%TYPE
+ )
+ is
+ v_value_id apm_parameter_values.value_id%TYPE;
+ cursor cur is
+ select parameter_id, default_value
+ from apm_parameters
+ where package_key = initialize_parameters.package_key;
+ begin
+ -- need to initialize all params for this type
+ for cur_val in cur
+ loop
+ v_value_id := apm_parameter_value.new(
+ package_id => initialize_parameters.package_id,
+ parameter_id => cur_val.parameter_id,
+ attr_value => cur_val.default_value
+ );
+ end loop;
+ end initialize_parameters;
+
+ 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
+ is
+ 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(
+ package_key => apm_package.new.package_key
+ );
+ v_num_instances := apm_package.num_instances(
+ package_key => apm_package.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 = apm_package.new.package_key;
+ return v_package_id;
+ else
+ v_package_id := acs_object.new(
+ object_id => package_id,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ if instance_name is null then
+ v_instance_name := package_key || ' ' || v_package_id;
+ else
+ v_instance_name := instance_name;
+ end if;
+
+ select package_type into v_package_type
+ from apm_package_types
+ where package_key = apm_package.new.package_key;
+
+ insert into apm_packages
+ (package_id, package_key, instance_name)
+ values
+ (v_package_id, 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;
+
+ initialize_parameters(
+ package_id => v_package_id,
+ package_key => apm_package.new.package_key
+ );
+ return v_package_id;
+
+ end if;
+end new;
+
+ procedure delete (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ cursor all_values is
+ select value_id from apm_parameter_values
+ where package_id = apm_package.delete.package_id;
+ cursor all_site_nodes is
+ select node_id from site_nodes
+ where object_id = apm_package.delete.package_id;
+ begin
+ -- Delete all parameters.
+ for cur_val in all_values loop
+ apm_parameter_value.delete(value_id => cur_val.value_id);
+ end loop;
+ delete from apm_applications where application_id = apm_package.delete.package_id;
+ delete from apm_services where service_id = apm_package.delete.package_id;
+ delete from apm_packages where package_id = apm_package.delete.package_id;
+ -- Delete the site nodes for the objects.
+ for cur_val in all_site_nodes loop
+ site_node.delete(cur_val.node_id);
+ end loop;
+ -- Delete the object.
+ acs_object.delete (
+ object_id => package_id
+ );
+ end delete;
+
+ function singleton_p (
+ package_key in apm_packages.package_key%TYPE
+ ) return integer
+ is
+ 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';
+ return v_singleton_p;
+
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end singleton_p;
+
+ function num_instances (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_num_instances integer;
+ begin
+ select count(*) into v_num_instances
+ from apm_packages
+ where package_key = num_instances.package_key;
+ return v_num_instances;
+
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end num_instances;
+
+ function name (
+ package_id in apm_packages.package_id%TYPE
+ ) return varchar2
+ is
+ 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 name;
+
+ procedure enable (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ update apm_packages
+ set enabled_p = 't'
+ where package_id = enable.package_id;
+ end enable;
+
+ procedure disable (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ update apm_packages
+ set enabled_p = 'f'
+ where package_id = disable.package_id;
+ end disable;
+
+ function highest_version (
+ package_key in apm_package_types.package_key%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ 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;
+ return v_version_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end highest_version;
+end apm_package;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ begin
+ if version_id is null then
+ select acs_object_id_seq.nextval
+ into v_version_id
+ from dual;
+ else
+ v_version_id := version_id;
+ end if;
+ v_version_id := acs_object.new(
+ object_id => version_id,
+ object_type => 'apm_package_version'
+ );
+ 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, package_key, version_name, version_uri,
+ summary, description_format, description,
+ release_date, vendor, vendor_uri,
+ installed_p, data_model_loaded_p);
+ return v_version_id;
+ end new;
+
+ procedure delete (
+ version_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_owners
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_files
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_dependencies
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_versions
+ where version_id = apm_package_version.delete.version_id;
+
+ acs_object.delete(apm_package_version.delete.version_id);
+
+ end delete;
+
+ procedure enable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions set enabled_p = 't'
+ where version_id = enable.version_id;
+ end enable;
+
+ procedure disable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions
+ set enabled_p = 'f'
+ where version_id = disable.version_id;
+ end disable;
+
+
+ function copy(
+ version_id in apm_package_versions.version_id%TYPE,
+ new_version_id in apm_package_versions.version_id%TYPE default null,
+ new_version_name in apm_package_versions.version_name%TYPE,
+ new_version_uri in apm_package_versions.version_uri%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ v_version_id integer;
+ begin
+ v_version_id := acs_object.new(
+ object_id => new_version_id,
+ object_type => 'apm_package_version'
+ );
+
+ 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 copy;
+
+ 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ version_unchanged_p integer;
+ begin
+ -- Determine if version has changed.
+ select decode(count(*),0,0,1) 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 := copy(
+ version_id => edit.version_id,
+ new_version_id => edit.new_version_id,
+ new_version_name => edit.version_name,
+ new_version_uri => 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 = trunc(sysdate),
+ 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 edit;
+
+ 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
+ is
+ 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;
+ return v_file_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ if file_id is null then
+ select acs_object_id_seq.nextval into v_file_id from dual;
+ else
+ v_file_id := 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);
+ return v_file_id;
+ end add_file;
+
+ -- 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
+ )
+ is
+ begin
+ delete from apm_package_files
+ where version_id = remove_file.version_id
+ and path = remove_file.path;
+ end remove_file;
+
+
+-- 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
+ is
+ 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 add_interface;
+
+ procedure remove_interface(
+ interface_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_interface.interface_id;
+ end remove_interface;
+
+ 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
+ )
+ is
+ 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;
+ remove_interface(v_dep_id);
+ end remove_interface;
+
+ -- 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
+ is
+ 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 add_dependency;
+
+ procedure remove_dependency(
+ dependency_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_dependency.dependency_id;
+ end remove_dependency;
+
+
+ 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
+ )
+ is
+ 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;
+ remove_dependency(v_dep_id);
+ end remove_dependency;
+
+ function sortable_version_name (
+ version_name in apm_package_versions.version_name%TYPE
+ ) return varchar2
+ is
+ a_start integer;
+ a_end integer;
+ a_order varchar2(1000);
+ a_char char(1);
+ a_seen_letter char(1) := '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
+ raise_application_error(-20000, 'Expected number at position ' || a_start);
+ end if;
+ if a_end - a_start > 4 then
+ 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.';
+ elsif a_char = 'a' then
+ a_order := a_order || ' 1A.';
+ elsif a_char = 'b' then
+ a_order := a_order || ' 2B.';
+ else
+ -- uhoh... some wacky character. bomb
+ -- raise_application_error(-20000, 'Illegal character ''' || a_char ||
+ -- ' in version name ' || version_name || '''');
+ a_order := a_order || ' OD.';
+ end if;
+
+ -- can't have something like 3.3a1b2 - just one letter allowed!
+ if a_seen_letter = 't' then
+ 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 sortable_version_name;
+
+ 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 is
+ a_order_a varchar2(1000);
+ a_order_b varchar2(1000);
+ begin
+ a_order_a := sortable_version_name(version_name_one);
+ a_order_b := sortable_version_name(version_name_two);
+ if a_order_a < a_order_b then
+ return -1;
+ elsif a_order_a > a_order_b then
+ return 1;
+ end if;
+ return 0;
+ end version_name_greater;
+
+ 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
+ is
+ v_pos1 integer;
+ v_pos2 integer;
+ 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 := instr(v_path, '.', -1);
+ 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 version_name_greater(upgrade_p.initial_version_name, v_version_from) <= 0 and
+ 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 upgrade_p;
+
+ procedure upgrade(
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ 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;
+
+ end upgrade;
+
+end apm_package_version;
+/
+show errors
+
+create or replace package body apm_package_type
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE
+ is
+ 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 create_type.package_key;
+ end create_type;
+
+ 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
+ is
+ begin
+ UPDATE apm_package_types SET
+ pretty_name = nvl(update_type.pretty_name, pretty_name),
+ pretty_plural = nvl(update_type.pretty_plural, pretty_plural),
+ package_uri = nvl(update_type.package_uri, package_uri),
+ package_type = nvl(update_type.package_type, package_type),
+ spec_file_path = nvl(update_type.spec_file_path, spec_file_path),
+ spec_file_mtime = nvl(update_type.spec_file_mtime, spec_file_mtime),
+ singleton_p = nvl(update_type.singleton_p, singleton_p)
+ where package_key = update_type.package_key;
+ return update_type.package_key;
+ end update_type;
+
+ procedure drop_type (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ cursor all_package_ids is
+ select package_id
+ from apm_packages
+ where package_key = drop_type.package_key;
+
+ cursor all_parameters is
+ select parameter_id from apm_parameters
+ where package_key = drop_type.package_key;
+
+ cursor all_versions is
+ select version_id from apm_package_versions
+ where package_key = drop_type.package_key;
+ begin
+ if cascade_p = 't' then
+ for cur_val in all_package_ids
+ loop
+ apm_package.delete(
+ package_id => cur_val.package_id
+ );
+ end loop;
+ -- Unregister all parameters.
+ for cur_val in all_parameters
+ loop
+ apm.unregister_parameter(parameter_id => cur_val.parameter_id);
+ end loop;
+
+ -- Unregister all versions
+ for cur_val in all_versions
+ loop
+ apm_package_version.delete(version_id => cur_val.version_id);
+ end loop;
+ end if;
+ delete from apm_package_types
+ where package_key = drop_type.package_key;
+ end drop_type;
+
+ function num_parameters (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_count integer;
+ begin
+ select count(*) into v_count
+ from apm_parameters
+ where package_key = num_parameters.package_key;
+ return v_count;
+ end num_parameters;
+
+end apm_package_type;
+
+
+/
+show errors
+
+create or replace package body 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
+ is
+ v_value_id apm_parameter_values.value_id%TYPE;
+ begin
+ v_value_id := acs_object.new(
+ object_id => value_id,
+ object_type => 'apm_parameter_value'
+ );
+ insert into apm_parameter_values
+ (value_id, package_id, parameter_id, attr_value)
+ values
+ (v_value_id, apm_parameter_value.new.package_id,
+ apm_parameter_value.new.parameter_id,
+ apm_parameter_value.new.attr_value);
+ return v_value_id;
+ end new;
+
+ procedure delete (
+ value_id in apm_parameter_values.value_id%TYPE default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where value_id = apm_parameter_value.delete.value_id;
+ acs_object.delete(value_id);
+ end delete;
+
+ end apm_parameter_value;
+/
+show errors;
+
+create or replace package body 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
+ is
+ v_application_id integer;
+ begin
+ v_application_id := apm_package.new (
+ package_id => application_id,
+ instance_name => instance_name,
+ package_key => package_key,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ return v_application_id;
+ end new;
+
+ procedure delete (
+ application_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+ delete from apm_applications
+ where application_id = apm_application.delete.application_id;
+ apm_package.delete(
+ package_id => application_id);
+ end delete;
+
+end;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_service_id integer;
+ begin
+ v_service_id := apm_package.new (
+ package_id => service_id,
+ instance_name => instance_name,
+ package_key => package_key,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ return v_service_id;
+ end new;
+
+ procedure delete (
+ service_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+ delete from apm_services
+ where service_id = apm_service.delete.service_id;
+ apm_package.delete(
+ package_id => service_id
+ );
+ end delete;
+
+end;
+/
+show errors
+
+alter table group_member_index drop constraint group_member_index_pk;
+alter table group_member_index add constraint group_member_index_pk primary key (member_id, group_id, rel_id);
+
+@@security-drop.sql
+@@security-create.sql
+
+create or replace view acs_messages_all as
+ select m.message_id, m.reply_to, o.context_id, r.title, r.publish_date,
+ r.mime_type, r.content, o.creation_user
+ from acs_objects o, cr_items i, cr_revisions r, acs_messages m
+ where o.object_id = m.message_id and i.item_id = m.message_id
+ and r.revision_id = i.live_revision;
+
+@@../../acs-content-repository/sql/packages-create
+@@../../acs-workflow/sql/workflow-case-package
+@@../../acs-workflow/sql/workflow-package
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0rc0-4.0.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0rc0-4.0.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.0rc0-4.0.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,1788 @@
+--
+-- /web/bquinn/packages/acs-kernel/sql/upgrade-4.0rc0-4.0.sql
+--
+-- Upgrade script from ACS 4.0 RC#0 to ACS 4.0 Production
+--
+-- @author Bryan Quinn (bquinn@arsdigita.com)
+-- @creation-date Mon Oct 23 10:26:18 2000
+-- @cvs-id $Id: upgrade-4.0rc0-4.0.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+-- Update the Content Repository
+@@ ../../acs-content-repository/sql/content-update.sql
+
+-- Update APM Procedures
+
+-- 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
+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
+ )
+ is
+ begin
+ apm_package_type.create_type(
+ package_key => register_package.package_key,
+ pretty_name => register_package.pretty_name,
+ pretty_plural => register_package.pretty_plural,
+ package_uri => register_package.package_uri,
+ package_type => register_package.package_type,
+ singleton_p => register_package.singleton_p,
+ spec_file_path => register_package.spec_file_path,
+ spec_file_mtime => spec_file_mtime
+ );
+ end register_package;
+
+ 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
+ is
+ begin
+
+ return apm_package_type.update_type(
+ package_key => update_package.package_key,
+ pretty_name => update_package.pretty_name,
+ pretty_plural => update_package.pretty_plural,
+ package_uri => update_package.package_uri,
+ package_type => update_package.package_type,
+ singleton_p => update_package.singleton_p,
+ spec_file_path => update_package.spec_file_path,
+ spec_file_mtime => update_package.spec_file_mtime
+ );
+
+ end update_package;
+
+
+ procedure unregister_package (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 't'
+ )
+ is
+ begin
+ apm_package_type.drop_type(
+ package_key => unregister_package.package_key,
+ cascade_p => unregister_package.cascade_p
+ );
+ end unregister_package;
+
+ function register_p (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_register_p integer;
+ begin
+ select decode(count(*),0,0,1) into v_register_p from apm_package_types
+ where package_key = register_p.package_key;
+ return v_register_p;
+ end register_p;
+
+ 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
+ )
+ is
+ begin
+ apm.register_package(
+ package_key => register_application.package_key,
+ pretty_name => register_application.pretty_name,
+ pretty_plural => register_application.pretty_plural,
+ package_uri => register_application.package_uri,
+ package_type => 'apm_application',
+ singleton_p => register_application.singleton_p,
+ spec_file_path => register_application.spec_file_path,
+ spec_file_mtime => register_application.spec_file_mtime
+ );
+ end register_application;
+
+ procedure unregister_application (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_application.package_key,
+ cascade_p => unregister_application.cascade_p
+ );
+ end unregister_application;
+
+ 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
+ )
+ is
+ begin
+ apm.register_package(
+ package_key => register_service.package_key,
+ pretty_name => register_service.pretty_name,
+ pretty_plural => register_service.pretty_plural,
+ package_uri => register_service.package_uri,
+ package_type => 'apm_service',
+ singleton_p => register_service.singleton_p,
+ spec_file_path => register_service.spec_file_path,
+ spec_file_mtime => register_service.spec_file_mtime
+ );
+ end register_service;
+
+ procedure unregister_service (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_service.package_key,
+ cascade_p => unregister_service.cascade_p
+ );
+ end unregister_service;
+
+ -- 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
+ is
+ v_parameter_id apm_parameters.parameter_id%TYPE;
+ cursor all_parameters is
+ select ap.package_id, v.parameter_id, p.default_value
+ from apm_parameters p, apm_parameter_values v, apm_packages ap
+ where p.package_key = ap.package_key
+ and v.package_id = ap.package_id
+ and p.parameter_id = v.parameter_id
+ and v.attr_value is null
+ and p.package_key = register_parameter.package_key;
+ begin
+ -- Create the new parameter.
+ v_parameter_id := acs_object.new(
+ object_id => parameter_id,
+ object_type => 'apm_parameter'
+ );
+
+ 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, register_parameter.description,
+ register_parameter.package_key, register_parameter.datatype,
+ register_parameter.default_value, register_parameter.section_name,
+ register_parameter.min_n_values, register_parameter.max_n_values);
+ -- Propagate parameter to new instances.
+ for cur_val in all_parameters
+ loop
+ apm.set_value(
+ package_id => cur_val.package_id,
+ parameter_id => cur_val.parameter_id,
+ attr_value => cur_val.default_value
+ );
+ end loop;
+ return v_parameter_id;
+ end register_parameter;
+
+ 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
+ is
+ begin
+ update apm_parameters
+ set parameter_name = nvl(update_parameter.parameter_name, parameter_name),
+ default_value = nvl(update_parameter.default_value, default_value),
+ datatype = nvl(update_parameter.datatype, datatype),
+ description = nvl(update_parameter.description, description),
+ section_name = nvl(update_parameter.section_name, section_name),
+ min_n_values = nvl(update_parameter.min_n_values, min_n_values),
+ max_n_values = nvl(update_parameter.max_n_values, max_n_values)
+ where parameter_id = update_parameter.parameter_id;
+ return parameter_id;
+ end;
+
+ function parameter_p(
+ package_key in apm_package_types.package_key%TYPE,
+ parameter_name in apm_parameters.parameter_name%TYPE
+ ) return integer
+ is
+ v_parameter_p integer;
+ begin
+ select decode(count(*),0,0,1) 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 parameter_p;
+
+ procedure unregister_parameter (
+ parameter_id in apm_parameters.parameter_id%TYPE
+ default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where parameter_id = unregister_parameter.parameter_id;
+ delete from apm_parameters
+ where parameter_id = unregister_parameter.parameter_id;
+ acs_object.delete(parameter_id);
+ end unregister_parameter;
+
+ function id_for_name (
+ parameter_name in apm_parameters.parameter_name%TYPE,
+ package_key in apm_parameters.package_key%TYPE
+ ) return apm_parameters.parameter_id%TYPE
+ is
+ 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 id_for_name;
+
+ 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
+ is
+ 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 get_value;
+
+ 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
+ is
+ 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(
+ parameter_id => v_parameter_id,
+ package_id => get_value.package_id
+ );
+ end get_value;
+
+
+ -- 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
+ )
+ is
+ 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
+ when NO_DATA_FOUND
+ then
+ v_value_id := apm_parameter_value.new(
+ package_id => package_id,
+ parameter_id => parameter_id,
+ attr_value => attr_value
+ );
+ end set_value;
+
+ 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
+ )
+ is
+ 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);
+ apm.set_value(
+ parameter_id => v_parameter_id,
+ package_id => set_value.package_id,
+ attr_value => set_value.attr_value
+ );
+ exception
+ when NO_DATA_FOUND
+ then
+ RAISE_APPLICATION_ERROR(-20000, 'The specified package ' || set_value.package_id ||
+ ' does not exist in the system.');
+ end set_value;
+end apm;
+/
+show errors
+
+create or replace package body apm_package
+as
+ procedure initialize_parameters (
+ package_id in apm_packages.package_id%TYPE,
+ package_key in apm_package_types.package_key%TYPE
+ )
+ is
+ v_value_id apm_parameter_values.value_id%TYPE;
+ cursor cur is
+ select parameter_id, default_value
+ from apm_parameters
+ where package_key = initialize_parameters.package_key;
+ begin
+ -- need to initialize all params for this type
+ for cur_val in cur
+ loop
+ v_value_id := apm_parameter_value.new(
+ package_id => initialize_parameters.package_id,
+ parameter_id => cur_val.parameter_id,
+ attr_value => cur_val.default_value
+ );
+ end loop;
+ end initialize_parameters;
+
+ 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
+ is
+ 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(
+ package_key => apm_package.new.package_key
+ );
+ v_num_instances := apm_package.num_instances(
+ package_key => apm_package.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 = apm_package.new.package_key;
+ return v_package_id;
+ else
+ v_package_id := acs_object.new(
+ object_id => package_id,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ if instance_name is null then
+ v_instance_name := package_key || ' ' || v_package_id;
+ else
+ v_instance_name := instance_name;
+ end if;
+
+ select package_type into v_package_type
+ from apm_package_types
+ where package_key = apm_package.new.package_key;
+
+ insert into apm_packages
+ (package_id, package_key, instance_name)
+ values
+ (v_package_id, 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;
+
+ initialize_parameters(
+ package_id => v_package_id,
+ package_key => apm_package.new.package_key
+ );
+ return v_package_id;
+
+ end if;
+end new;
+
+ procedure delete (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ cursor all_values is
+ select value_id from apm_parameter_values
+ where package_id = apm_package.delete.package_id;
+ cursor all_site_nodes is
+ select node_id from site_nodes
+ where object_id = apm_package.delete.package_id;
+ begin
+ -- Delete all parameters.
+ for cur_val in all_values loop
+ apm_parameter_value.delete(value_id => cur_val.value_id);
+ end loop;
+ delete from apm_applications where application_id = apm_package.delete.package_id;
+ delete from apm_services where service_id = apm_package.delete.package_id;
+ delete from apm_packages where package_id = apm_package.delete.package_id;
+ -- Delete the site nodes for the objects.
+ for cur_val in all_site_nodes loop
+ site_node.delete(cur_val.node_id);
+ end loop;
+ -- Delete the object.
+ acs_object.delete (
+ object_id => package_id
+ );
+ end delete;
+
+ function singleton_p (
+ package_key in apm_packages.package_key%TYPE
+ ) return integer
+ is
+ 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';
+ return v_singleton_p;
+
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end singleton_p;
+
+ function num_instances (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_num_instances integer;
+ begin
+ select count(*) into v_num_instances
+ from apm_packages
+ where package_key = num_instances.package_key;
+ return v_num_instances;
+
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end num_instances;
+
+ function name (
+ package_id in apm_packages.package_id%TYPE
+ ) return varchar2
+ is
+ 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 name;
+
+ procedure enable (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ update apm_packages
+ set enabled_p = 't'
+ where package_id = enable.package_id;
+ end enable;
+
+ procedure disable (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ update apm_packages
+ set enabled_p = 'f'
+ where package_id = disable.package_id;
+ end disable;
+
+ function highest_version (
+ package_key in apm_package_types.package_key%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ 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;
+ return v_version_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end highest_version;
+end apm_package;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ begin
+ if version_id is null then
+ select acs_object_id_seq.nextval
+ into v_version_id
+ from dual;
+ else
+ v_version_id := version_id;
+ end if;
+ v_version_id := acs_object.new(
+ object_id => version_id,
+ object_type => 'apm_package_version'
+ );
+ 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, package_key, version_name, version_uri,
+ summary, description_format, description,
+ release_date, vendor, vendor_uri,
+ installed_p, data_model_loaded_p);
+ return v_version_id;
+ end new;
+
+ procedure delete (
+ version_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_owners
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_files
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_dependencies
+ where version_id = apm_package_version.delete.version_id;
+
+ delete from apm_package_versions
+ where version_id = apm_package_version.delete.version_id;
+
+ acs_object.delete(apm_package_version.delete.version_id);
+
+ end delete;
+
+ procedure enable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions set enabled_p = 't'
+ where version_id = enable.version_id;
+ end enable;
+
+ procedure disable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions
+ set enabled_p = 'f'
+ where version_id = disable.version_id;
+ end disable;
+
+
+ function copy(
+ version_id in apm_package_versions.version_id%TYPE,
+ new_version_id in apm_package_versions.version_id%TYPE default null,
+ new_version_name in apm_package_versions.version_name%TYPE,
+ new_version_uri in apm_package_versions.version_uri%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ v_version_id integer;
+ begin
+ v_version_id := acs_object.new(
+ object_id => new_version_id,
+ object_type => 'apm_package_version'
+ );
+
+ 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 copy;
+
+ 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ version_unchanged_p integer;
+ begin
+ -- Determine if version has changed.
+ select decode(count(*),0,0,1) 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 := copy(
+ version_id => edit.version_id,
+ new_version_id => edit.new_version_id,
+ new_version_name => edit.version_name,
+ new_version_uri => 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 = trunc(sysdate),
+ 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 edit;
+
+ 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
+ is
+ 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;
+ return v_file_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ if file_id is null then
+ select acs_object_id_seq.nextval into v_file_id from dual;
+ else
+ v_file_id := 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);
+ return v_file_id;
+ end add_file;
+
+ -- 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
+ )
+ is
+ begin
+ delete from apm_package_files
+ where version_id = remove_file.version_id
+ and path = remove_file.path;
+ end remove_file;
+
+
+-- 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
+ is
+ 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 add_interface;
+
+ procedure remove_interface(
+ interface_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_interface.interface_id;
+ end remove_interface;
+
+ 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
+ )
+ is
+ 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;
+ remove_interface(v_dep_id);
+ end remove_interface;
+
+ -- 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
+ is
+ 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 add_dependency;
+
+ procedure remove_dependency(
+ dependency_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_dependency.dependency_id;
+ end remove_dependency;
+
+
+ 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
+ )
+ is
+ 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;
+ remove_dependency(v_dep_id);
+ end remove_dependency;
+
+ function sortable_version_name (
+ version_name in apm_package_versions.version_name%TYPE
+ ) return varchar2
+ is
+ a_start integer;
+ a_end integer;
+ a_order varchar2(1000);
+ a_char char(1);
+ a_seen_letter char(1) := '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
+ raise_application_error(-20000, 'Expected number at position ' || a_start);
+ end if;
+ if a_end - a_start > 4 then
+ 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.';
+ elsif a_char = 'a' then
+ a_order := a_order || ' 1A.';
+ elsif a_char = 'b' then
+ a_order := a_order || ' 2B.';
+ end if;
+
+ -- can't have something like 3.3a1b2 - just one letter allowed!
+ if a_seen_letter = 't' then
+ 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 sortable_version_name;
+
+ 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 is
+ a_order_a varchar2(1000);
+ a_order_b varchar2(1000);
+ begin
+ a_order_a := sortable_version_name(version_name_one);
+ a_order_b := sortable_version_name(version_name_two);
+ if a_order_a < a_order_b then
+ return -1;
+ elsif a_order_a > a_order_b then
+ return 1;
+ end if;
+ return 0;
+ end version_name_greater;
+
+ 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
+ is
+ v_pos1 integer;
+ v_pos2 integer;
+ 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 := instr(v_path, '.', -1);
+ 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 version_name_greater(upgrade_p.initial_version_name, v_version_from) <= 0 and
+ 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 upgrade_p;
+
+ procedure upgrade(
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ 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;
+
+ end upgrade;
+
+end apm_package_version;
+/
+show errors
+
+create or replace package body 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
+ )
+ is
+ 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);
+ end create_type;
+
+ 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
+ is
+ begin
+ UPDATE apm_package_types SET
+ pretty_name = nvl(update_type.pretty_name, pretty_name),
+ pretty_plural = nvl(update_type.pretty_plural, pretty_plural),
+ package_uri = nvl(update_type.package_uri, package_uri),
+ package_type = nvl(update_type.package_type, package_type),
+ spec_file_path = nvl(update_type.spec_file_path, spec_file_path),
+ spec_file_mtime = nvl(update_type.spec_file_mtime, spec_file_mtime),
+ singleton_p = nvl(update_type.singleton_p, singleton_p)
+ where package_key = update_type.package_key;
+ return update_type.package_key;
+ end update_type;
+
+ procedure drop_type (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ cursor all_package_ids is
+ select package_id
+ from apm_packages
+ where package_key = drop_type.package_key;
+
+ cursor all_parameters is
+ select parameter_id from apm_parameters
+ where package_key = drop_type.package_key;
+
+ cursor all_versions is
+ select version_id from apm_package_versions
+ where package_key = drop_type.package_key;
+ begin
+ if cascade_p = 't' then
+ for cur_val in all_package_ids
+ loop
+ apm_package.delete(
+ package_id => cur_val.package_id
+ );
+ end loop;
+ -- Unregister all parameters.
+ for cur_val in all_parameters
+ loop
+ apm.unregister_parameter(parameter_id => cur_val.parameter_id);
+ end loop;
+
+ -- Unregister all versions
+ for cur_val in all_versions
+ loop
+ apm_package_version.delete(version_id => cur_val.version_id);
+ end loop;
+ end if;
+ delete from apm_package_types
+ where package_key = drop_type.package_key;
+ end drop_type;
+
+ function num_parameters (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_count integer;
+ begin
+ select count(*) into v_count
+ from apm_parameters
+ where package_key = num_parameters.package_key;
+ return v_count;
+ end num_parameters;
+
+end apm_package_type;
+
+
+/
+show errors
+
+create or replace package body 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
+ is
+ v_value_id apm_parameter_values.value_id%TYPE;
+ begin
+ v_value_id := acs_object.new(
+ object_id => value_id,
+ object_type => 'apm_parameter_value'
+ );
+ insert into apm_parameter_values
+ (value_id, package_id, parameter_id, attr_value)
+ values
+ (v_value_id, apm_parameter_value.new.package_id,
+ apm_parameter_value.new.parameter_id,
+ apm_parameter_value.new.attr_value);
+ return v_value_id;
+ end new;
+
+ procedure delete (
+ value_id in apm_parameter_values.value_id%TYPE default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where value_id = apm_parameter_value.delete.value_id;
+ acs_object.delete(value_id);
+ end delete;
+
+ end apm_parameter_value;
+/
+show errors;
+
+create or replace package body 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
+ is
+ v_application_id integer;
+ begin
+ v_application_id := apm_package.new (
+ package_id => application_id,
+ instance_name => instance_name,
+ package_key => package_key,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ return v_application_id;
+ end new;
+
+ procedure delete (
+ application_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+ delete from apm_applications
+ where application_id = apm_application.delete.application_id;
+ apm_package.delete(
+ package_id => application_id);
+ end delete;
+
+end;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_service_id integer;
+ begin
+ v_service_id := apm_package.new (
+ package_id => service_id,
+ instance_name => instance_name,
+ package_key => package_key,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ return v_service_id;
+ end new;
+
+ procedure delete (
+ service_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+ delete from apm_services
+ where service_id = apm_service.delete.service_id;
+ apm_package.delete(
+ package_id => service_id
+ );
+ end delete;
+
+end;
+/
+show errors
+
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1-4.1.1.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1-4.1.1.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1-4.1.1.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,189 @@
+--
+-- /packages/acs-kernel/sql/upgrade/upgrade-4.1-4.1.1.sql
+--
+-- Upgrades ACS Kernel 4.1 to ACS Kernel 4.1.1
+--
+-- @author Multiple
+-- @creation-date 2001-01-23
+-- @cvs-id $Id: upgrade-4.1-4.1.1.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+
+--------------------------------------------------------------
+-- Relational Constraints Views
+-- oumi@arsdigita.com
+-- 1/23/2001
+--
+-- CHANGES
+-- Added some views and modified one view to fix minor bugs
+-- and make it possible to fix some UI issues in ACS Subsites
+--------------------------------------------------------------
+
+-- 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
+--
+create or replace view rc_all_constraints as
+select group_ancestor_map.group_id,
+ type_map.object_type as rel_type,
+ rel_constraints.rel_segment,
+ rel_constraints.rel_side,
+ required_rel_segment
+ from rel_constraints,
+ rel_segments,
+ (select object_type, ancestor_type
+ from acs_object_type_supertype_map
+ union all
+ select object_type, object_type
+ from acs_object_types) type_map,
+ (select component_id as group_id,
+ group_id as ancestor_group_id
+ from group_component_map
+ union all
+ select group_id as component_group_id,
+ group_id as ancestor_group_id
+ from groups) group_ancestor_map
+ where rel_constraints.rel_segment = rel_segments.segment_id
+ and rel_segments.group_id = group_ancestor_map.ancestor_group_id
+ and rel_segments.rel_type = type_map.ancestor_type;
+
+
+create or replace 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 or replace 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 or replace 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;
+
+
+-- 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 or replace 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 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;
+
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1.1-4.2.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1.1-4.2.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1.1-4.2.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,1086 @@
+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
+as
+
+ 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
+ is
+ v_node_id site_nodes.node_id%TYPE;
+ v_directory_p site_nodes.directory_p%TYPE;
+ begin
+ if 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_application_error (
+ -20000,
+ 'Node ' || parent_id || ' is not a directory'
+ );
+ end if;
+ end if;
+
+ v_node_id := acs_object.new (
+ object_id => node_id,
+ object_type => 'site_node',
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ 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;
+
+ procedure delete (
+ node_id in site_nodes.node_id%TYPE
+ )
+ is
+ begin
+ delete from site_nodes
+ where node_id = site_node.delete.node_id;
+
+ acs_object.delete(node_id);
+ end;
+
+ function find_pattern (
+ node_id in site_nodes.node_id%TYPE
+ ) return site_nodes.node_id%TYPE
+ is
+ 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;
+ 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 node_id;
+ else
+ return find_pattern(v_parent_id);
+ end if;
+ end;
+
+ function node_id (
+ url in varchar2,
+ parent_id in site_nodes.node_id%TYPE default null
+ ) return site_nodes.node_id%TYPE
+ is
+ v_pos integer;
+ v_first site_nodes.name%TYPE;
+ v_rest varchar2(4000);
+ v_node_id integer;
+ v_pattern_p site_nodes.pattern_p%TYPE;
+ v_url varchar2(4000);
+ v_directory_p site_nodes.directory_p%TYPE;
+ v_trailing_slash_p char(1);
+ begin
+ v_url := 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 nvl(parent_id, 3.14) = nvl(site_node.node_id.parent_id, 3.14)
+ and nvl(name, chr(10)) = nvl(v_first, chr(10));
+ exception
+ when no_data_found then
+ return find_pattern(parent_id);
+ end;
+
+ if v_rest is null then
+ if v_trailing_slash_p = 't' and v_directory_p = 'f' then
+ return find_pattern(parent_id);
+ else
+ return v_node_id;
+ end if;
+ else
+ return node_id(v_rest, v_node_id);
+ end if;
+ end;
+
+ function url (
+ node_id in site_nodes.node_id%TYPE
+ ) return varchar2
+ is
+ v_parent_id site_nodes.node_id%TYPE;
+ v_name site_nodes.name%TYPE;
+ v_directory_p site_nodes.directory_p%TYPE;
+ begin
+ if 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 url(v_parent_id) || v_name || '/';
+ else
+ return url(v_parent_id) || v_name;
+ end if;
+ end;
+
+end;
+/
+show errors
+
+--------------------------------------------------------------
+-- Relational Segments Views
+-- oumi@arsdigita.com
+-- 2/13/2001
+--
+-- CHANGES
+-- Optimization improvement of rel_segment_party_map.
+-- Added rel_segment_group_rel_type_map. This view simplifies
+-- the logic in other queries and views.
+--------------------------------------------------------------
+
+create or replace 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 or replace 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';
+
+
+-- 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 or replace 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);
+
+
+--------------------------------------------------------------
+-- Relational Constraints Views
+-- oumi@arsdigita.com
+-- 2/9/2001 - 2/13/2001
+--
+-- CHANGES
+--
+-- Added rc_segment_required_segment_map and
+-- rc_dependency_levels (these views save us from having to
+-- write, tune, and comment connect by queries on
+-- rel_constraints in our application code).
+
+-- Rewrote rc_all_constraints to use the new
+-- rel_segment_group_rel_type_map view. More importantly, the
+-- rc_all_constraints view now avoids returning circular
+-- constraints (see comments on the rc_all_constraints view).
+--
+-- Fixed rc_valid_rel_types. The query under "UNION ALL"
+-- wasn't limiting the all_constraints view to side one
+-- constraints. The result was that fewer rows were returned
+-- than what you might expect.
+--------------------------------------------------------------
+
+-- 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 or replace 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 or replace 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;
+
+
+-- 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 or replace 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 or replace 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
+;
+
+--------------------------------------------------------------
+-- Relationship Type Views
+-- oumi@arsdigita.com
+-- 2/9/2001
+--
+-- created in acs-relationships-create.sql
+--------------------------------------------------------------
+
+-- 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 or replace 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 or replace 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;
+
+
+--------------------------------------------------------------
+-- community-core.sql
+-- oumi@arsdigita.com
+-- 2/13/2001
+--
+-- CHANGES
+-- Added first_names and last_name as attributes of a person.
+-- The subsite pages use this metadata to generate forms for
+-- adding parties to a subsite.
+--------------------------------------------------------------
+
+declare
+ attr_id integer;
+begin
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'person',
+ attribute_name => 'first_names',
+ datatype => 'string',
+ pretty_name => 'First Names',
+ pretty_plural => 'First Names',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+ attr_id := acs_attribute.create_attribute (
+ object_type => 'person',
+ attribute_name => 'last_name',
+ datatype => 'string',
+ pretty_name => 'Last Name',
+ pretty_plural => 'Last Names',
+ min_n_values => 0,
+ max_n_values => 1
+ );
+
+end;
+/
+show errors
+
+
+--------------------------------------------------------------
+-- groups-create.sql
+-- oumi@arsdigita.com
+-- 2/22/2001
+--
+-- Changes:
+-- Added rel_type to the group_approved_member_map view.
+-- Fixed the approval policy / default new member policy stuff
+--------------------------------------------------------------
+
+/* Restrict membership to persons. Previously, a group could be a member
+ * of another group. Now, only a person can be a member of a group.
+ * A group can still be a component of another group through a composition
+ * relation
+ */
+update acs_rel_types
+set object_type_two='person'
+where rel_type = 'membership_rel';
+
+create or replace 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';
+
+
+-- Replace approval_policy and default_new_member_policy with join_policy,
+-- because the original columns didn't make much sense, had no check
+-- constraints, weren't used by any code, etc.
+alter table group_types add (
+ default_join_policy varchar2(30) default 'open' not null
+ constraint group_types_join_policy_ck
+ check (default_join_policy in
+ ('open', 'needs approval', 'closed'))
+);
+alter table group_types drop column approval_policy;
+alter table group_types drop column default_new_member_policy;
+
+alter table groups add (
+ join_policy varchar2(30) default 'open' not null
+ constraint groups_join_policy_ck
+ check (join_policy in
+ ('open', 'needs approval', 'closed'))
+);
+
+alter table membership_rels drop constraint membership_rel_mem_ck;
+alter table membership_rels add constraint membership_rel_mem_ck
+ check (member_state in ('approved', 'needs approval', 'banned', 'rejected', 'deleted'));
+
+update membership_rels
+ set member_state = 'needs approval'
+where member_state is null;
+
+commit;
+
+alter table membership_rels modify
+ member_state not null;
+
+
+-- Now we change the default member_state value in the pl/sql packages
+
+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 body 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
+ is
+ v_rel_id integer;
+ begin
+ v_rel_id := acs_rel.new (
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two,
+ context_id => object_id_one,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into membership_rels
+ (rel_id, member_state)
+ values
+ (v_rel_id, new.member_state);
+
+ return v_rel_id;
+ end;
+
+ procedure ban (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'banned'
+ where rel_id = ban.rel_id;
+ end;
+
+ procedure approve (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'approved'
+ where rel_id = approve.rel_id;
+ end;
+
+ procedure reject (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'rejected'
+ where rel_id = reject.rel_id;
+ end;
+
+ procedure unapprove (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'needs approval'
+ where rel_id = unapprove.rel_id;
+ end;
+
+ procedure deleted (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'deleted'
+ where rel_id = deleted.rel_id;
+ end;
+
+ procedure delete (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ acs_rel.delete(rel_id);
+ end;
+
+ function check_index (
+ group_id in groups.group_id%TYPE,
+ member_id in parties.party_id%TYPE,
+ container_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ n_rows integer;
+ 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';
+ acs_log.error('membership_rel.check_representation',
+ 'Row missing from group_member_index: ' ||
+ 'group_id = ' || group_id || ', ' ||
+ 'member_id = ' || member_id || ', ' ||
+ 'container_id = ' || 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 = group_id) loop
+ if check_index(row.container_id, member_id, container_id) = 'f' then
+ result := 'f';
+ end if;
+ end loop;
+
+ return result;
+ end;
+
+ function check_representation (
+ rel_id in membership_rels.rel_id%TYPE
+ ) return char
+ is
+ group_id groups.group_id%TYPE;
+ member_id parties.party_id%TYPE;
+ result char(1);
+ begin
+ result := 't';
+
+ if acs_object.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 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';
+ 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;
+
+end membership_rel;
+/
+show errors
+
+-- Next, we add join_policy to the acs_group pl/sql package
+
+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
+
+create or replace package body 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
+ is
+ 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(group_id, object_type, creation_date, creation_user,
+ creation_ip, email, url, context_id);
+
+ v_join_policy := join_policy;
+
+ -- if join policy wasn't 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 = object_type;
+
+ if v_group_type_exists_p = 1 then
+ select default_join_policy into v_join_policy
+ from group_types
+ where group_type = object_type;
+ else
+ v_join_policy := 'open';
+ end if;
+ end if;
+
+ insert into groups
+ (group_id, group_name, join_policy)
+ values
+ (v_group_id, 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 new;
+
+
+ procedure delete (
+ group_id in groups.group_id%TYPE
+ )
+ is
+ begin
+
+ -- Delete all segments defined for this group
+ for row in (select segment_id
+ from rel_segments
+ where group_id = acs_group.delete.group_id) loop
+
+ 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 = acs_group.delete.group_id
+ or r.object_id_two = acs_group.delete.group_id)) loop
+ execute immediate 'begin ' || row.package_name || '.delete(' || row.rel_id || '); end;';
+ end loop;
+
+ party.delete(group_id);
+ end delete;
+
+ function name (
+ group_id in groups.group_id%TYPE
+ )
+ return varchar2
+ is
+ group_name varchar2(200);
+ begin
+ select group_name
+ into group_name
+ from groups
+ where group_id = name.group_id;
+
+ return group_name;
+ end name;
+
+ function member_p (
+ party_id in parties.party_id%TYPE
+ )
+ return char
+ is
+ begin
+ -- TO DO: implement this for real
+ return 't';
+ end member_p;
+
+ function check_representation (
+ group_id in groups.group_id%TYPE
+ ) return char
+ is
+ result char(1);
+ begin
+ result := 't';
+ 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;
+
+ acs_log.notice('acs_group.check_representation',
+ 'Done running check_representation on group ' || group_id);
+ return result;
+ end;
+
+end acs_group;
+/
+show errors
+
+--------------------------------------------------------------
+-- acs-permissions-create.sql
+-- oumi@arsdigita.com
+-- 2/21/2001
+--
+-- CHANGES
+--
+-- Modified acs_object_party_privilege_map to only map permissions on to
+-- approved members of groups and segments, rather than all members.
+--
+-- Added views to provide an alternative to
+-- acs_object_party_privilege_map that may be faster in many
+-- cases.
+--------------------------------------------------------------
+
+create or replace 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;
+
+create or replace 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 or replace 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;
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1b-4.1.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1b-4.1.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-4.1b-4.1.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,229 @@
+--
+-- /packages/acs-kernel/sql/upgrade/upgrade-4.1b-4.1.sql
+--
+-- Upgrades ACS Kernel 4.1 beta to ACS Kernel 4.1
+--
+-- @author Multiple
+-- @creation-date 2001-01-19
+-- @cvs-id $Id: upgrade-4.1b-4.1.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+
+
+
+-----------------------------
+-- PACKAGE ACS_OBJECT_TYPE
+-- mbryzek@arsdigita.com
+-- 1/19/2001
+--
+-- CHANGES
+-- Add is_subtype_p function
+-----------------------------
+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 body acs_object_type
+is
+
+ 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,
+ 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
+ )
+ is
+ v_package_name acs_object_types.package_name%TYPE;
+ begin
+ -- XXX This is a hack for losers who haven't created packages yet.
+ if package_name is null then
+ v_package_name := object_type;
+ else
+ v_package_name := 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
+ (object_type, pretty_name, pretty_plural, supertype, table_name,
+ id_column, abstract_p, type_extension_table, v_package_name,
+ name_method);
+ end create_type;
+
+ procedure drop_type (
+ object_type in acs_object_types.object_type%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ cursor c_attributes (object_type IN varchar) is
+ select attribute_name from acs_attributes where object_type = object_type;
+ begin
+
+ -- drop all the attributes associated with this type
+ for row in c_attributes (drop_type.object_type) loop
+ 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;
+ end drop_type;
+
+
+ function pretty_name (
+ object_type in acs_object_types.object_type%TYPE
+ ) return acs_object_types.pretty_name%TYPE
+ is
+ 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 pretty_name;
+
+
+ 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
+ is
+ v_result integer;
+ begin
+ select count(*) into v_result
+ from dual
+ 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);
+
+ if v_result > 0 then
+ return 't';
+ end if;
+
+ return 'f';
+
+ end is_subtype_p;
+
+end acs_object_type;
+/
+show errors
+
+
+
+-----------------------------
+-- View: rc_violations_by_removing_rel
+-- mbryzek@arsdigita.com
+-- 1/19/2001
+--
+-- CHANGES
+-- Fix bug in join
+-----------------------------
+
+-- 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 or replace 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;
+
+
+
+-------------------------------
+-- ACS_OBJECT_ATTRIBUTE_VIEW
+-- mbryzek@arsdigita.com
+-- 1/5/2001
+-------------------------------
+-- Use union all instead of union
+
+create or replace 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;
+
Index: openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-beta-1-beta-2.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/oracle/upgrade/Attic/upgrade-beta-1-beta-2.sql,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-kernel/sql/oracle/upgrade/upgrade-beta-1-beta-2.sql 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,2344 @@
+--
+-- Upgrade script from Beta 1 to Beta 2.
+--
+-- @author Richard Li (richardl@arsdigita.com)
+-- @cvs-id $Id: upgrade-beta-1-beta-2.sql,v 1.1 2001/03/20 22:51:56 donb Exp $
+-- @creation-date 10 October 2000
+
+@@ acs-logs-create
+
+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
+
+-- from acs-permissions
+
+create or replace package body 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
+ )
+ as
+ begin
+ insert into acs_permissions
+ (object_id, grantee_id, privilege)
+ values
+ (object_id, grantee_id, privilege);
+ exception
+ when dup_val_on_index then
+ return;
+ end grant_permission;
+
+ procedure revoke_permission (
+ object_id acs_permissions.object_id%TYPE,
+ grantee_id acs_permissions.grantee_id%TYPE,
+ privilege acs_permissions.privilege%TYPE
+ )
+ as
+ begin
+ delete from acs_permissions
+ where object_id = revoke_permission.object_id
+ and grantee_id = revoke_permission.grantee_id
+ and privilege = revoke_permission.privilege;
+ end revoke_permission;
+
+ function permission_p (
+ object_id acs_objects.object_id%TYPE,
+ party_id parties.party_id%TYPE,
+ privilege acs_privileges.privilege%TYPE
+ ) return char
+ as
+ exists_p char(1);
+ begin
+ select decode(count(*),0,'f',t') into exists_p
+ from acs_object_party_privilege_map
+ where object_id = permission_p.object_id
+ and party_id in (permission_p.party_id, -1)
+ and privilege = permission_p.privilege);
+ return exists_p;
+ end;
+
+end acs_permission;
+/
+show errors
+
+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'
+ )
+ 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
+
+-- from community-core.sql
+
+
+
+create or replace package body 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
+ )
+ return parties.party_id%TYPE
+ is
+ v_party_id parties.party_id%TYPE;
+ begin
+ v_party_id :=
+ acs_object.new(party_id, object_type,
+ creation_date, creation_user, creation_ip);
+
+ insert into parties
+ (party_id, email, url)
+ values
+ (v_party_id, lower(email), url);
+
+ return v_party_id;
+ end new;
+
+ procedure delete (
+ party_id in parties.party_id%TYPE
+ )
+ is
+ begin
+ delete from parties
+ where party_id = party.delete.party_id;
+
+ acs_object.delete(party_id);
+ end delete;
+
+ function name (
+ party_id in parties.party_id%TYPE
+ )
+ return varchar2
+ is
+ begin
+ if party_id = -1 then
+ return 'The Public';
+ else
+ return null;
+ end if;
+ end name;
+
+end party;
+/
+show errors
+
+create or replace package body 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'
+ )
+ return users.user_id%TYPE
+ is
+ v_user_id users.user_id%TYPE;
+ begin
+ v_user_id :=
+ person.new(user_id, object_type,
+ creation_date, creation_user, creation_ip,
+ email, url,
+ first_names, last_name);
+
+ insert into users
+ (user_id, password, salt, password_question, password_answer, screen_name,
+ email_verified_p)
+ values
+ (v_user_id, password, salt, password_question, password_answer, screen_name,
+ email_verified_p);
+
+ insert into user_preferences
+ (user_id)
+ values
+ (v_user_id);
+
+ return v_user_id;
+ end new;
+
+ function receives_alerts_p (
+ user_id in users.user_id%TYPE
+ )
+ return char
+ is
+ counter char(1);
+ begin
+ select decode(count(*),0,'f','t') into counter
+ from users
+ where no_alerts_until >= sysdate
+ and user_id = acs_user.receives_alerts_p.user_id;
+
+ return counter;
+ end receives_alerts_p;
+
+ procedure approve_email (
+ user_id in users.user_id%TYPE
+ )
+ is
+ begin
+ update users
+ set email_verified_p = 't'
+ where user_id = approve_email.user_id;
+ end approve_email;
+
+
+ procedure unapprove_email (
+ user_id in users.user_id%TYPE
+ )
+ is
+ begin
+ update users
+ set email_verified_p = 'f'
+ where user_id = unapprove_email.user_id;
+ end unapprove_email;
+
+ procedure delete (
+ user_id in users.user_id%TYPE
+ )
+ is
+ begin
+ delete from user_preferences
+ where user_id = acs_user.delete.user_id;
+
+ delete from users
+ where user_id = acs_user.delete.user_id;
+
+ person.delete(user_id);
+ end delete;
+
+end acs_user;
+/
+show errors
+
+-- from acs-relationships-create.sql
+
+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,
+ 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
+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,
+ creation_ip in acs_objects.creation_ip%TYPE default null
+ ) return acs_rels.rel_id%TYPE
+ is
+ 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 (
+ object_id => rel_id,
+ object_type => rel_type,
+ context_id => context_id,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ 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;
+
+ procedure delete (
+ rel_id in acs_rels.rel_id%TYPE
+ )
+ is
+ begin
+ delete from acs_rels
+ where rel_id = acs_rel.delete.rel_id;
+
+ acs_object.delete(rel_id);
+ end;
+
+end;
+/
+show errors
+
+-- from groups-create.sql
+
+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 null,
+ 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
+ );
+
+end membership_rel;
+/
+show errors
+
+create or replace package body 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 null,
+ 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
+ is
+ v_rel_id integer;
+ begin
+ v_rel_id := acs_rel.new (
+ rel_id => rel_id,
+ rel_type => rel_type,
+ object_id_one => object_id_one,
+ object_id_two => object_id_two,
+ context_id => object_id_one,
+ creation_user => creation_user,
+ creation_ip => creation_ip
+ );
+
+ insert into membership_rels
+ (rel_id, member_state)
+ values
+ (v_rel_id, new.member_state);
+
+ return v_rel_id;
+ end;
+
+ procedure ban (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'banned'
+ where rel_id = ban.rel_id;
+ end;
+
+ procedure approve (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'approved'
+ where rel_id = approve.rel_id;
+ end;
+
+ procedure reject (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'rejected'
+ where rel_id = reject.rel_id;
+ end;
+
+ procedure unapprove (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = ''
+ where rel_id = unapprove.rel_id;
+ end;
+
+ procedure deleted (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ update membership_rels
+ set member_state = 'deleted'
+ where rel_id = deleted.rel_id;
+ end;
+
+ procedure delete (
+ rel_id in membership_rels.rel_id%TYPE
+ )
+ is
+ begin
+ delete from membership_rels
+ where rel_id = membership_rel.delete.rel_id;
+
+ acs_rel.delete(rel_id);
+ end;
+
+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
+ ) 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;
+
+end acs_group;
+/
+show errors
+
+create or replace package body 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
+ )
+ return groups.group_id%TYPE
+ is
+ v_group_id groups.group_id%TYPE;
+ begin
+ v_group_id :=
+ party.new(group_id, object_type,
+ creation_date, creation_user, creation_ip, email, url);
+
+ insert into groups
+ (group_id, group_name)
+ values
+ (v_group_id, group_name);
+
+ return v_group_id;
+ end new;
+
+ procedure delete (
+ group_id in groups.group_id%TYPE
+ )
+ is
+ begin
+
+ for row 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
+ or r.object_id_two = group_id)) loop
+ membership_rel.delete(row.rel_id);
+ end loop;
+
+ for row 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
+ or r.object_id_two = group_id)) loop
+ composition_rel.delete(row.rel_id);
+ end loop;
+
+ acs_object.delete(group_id);
+ end delete;
+
+ function name (
+ group_id in groups.group_id%TYPE
+ )
+ return varchar2
+ is
+ group_name varchar2(200);
+ begin
+ select group_name
+ into group_name
+ from groups
+ where group_id = name.group_id;
+
+ return group_name;
+ end name;
+
+ function member_p (
+ party_id in parties.party_id%TYPE
+ )
+ return char
+ is
+ begin
+ -- TO DO: implement this for real
+ return 't';
+ end member_p;
+
+end acs_group;
+/
+show errors
+
+-- from apm
+create or replace package apm
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE;
+
+ 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.
+ function 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
+ ) return apm_package_types.package_key%TYPE;
+
+ -- 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'
+ );
+
+ function 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
+ ) return apm_package_types.package_key%TYPE;
+
+ -- 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 compare(
+ version_name_one in apm_package_versions.version_name%TYPE,
+ version_name_two in apm_package_versions.version_name%TYPE
+ ) return integer;
+
+end apm_package_version;
+/
+show errors
+
+create or replace package apm_package_type
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE;
+
+ 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'
+ );
+
+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
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE
+ is
+ begin
+ return apm_package_type.create_type(
+ package_key => register_package.package_key,
+ pretty_name => register_package.pretty_name,
+ pretty_plural => register_package.pretty_plural,
+ package_uri => register_package.package_uri,
+ package_type => register_package.package_type,
+ singleton_p => register_package.singleton_p,
+ spec_file_path => register_package.spec_file_path,
+ spec_file_mtime => spec_file_mtime
+ );
+ end register_package;
+
+ 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
+ is
+ begin
+
+ return apm_package_type.update_type(
+ package_key => update_package.package_key,
+ pretty_name => update_package.pretty_name,
+ pretty_plural => update_package.pretty_plural,
+ package_uri => update_package.package_uri,
+ package_type => update_package.package_type,
+ singleton_p => update_package.singleton_p,
+ spec_file_path => update_package.spec_file_path,
+ spec_file_mtime => update_package.spec_file_mtime
+ );
+
+ end update_package;
+
+
+ procedure unregister_package (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 't'
+ )
+ is
+ begin
+ apm_package_type.drop_type(
+ package_key => unregister_package.package_key,
+ cascade_p => unregister_package.cascade_p
+ );
+ end unregister_package;
+
+ function register_p (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_register_p integer;
+ begin
+ select decode(count(*),0,0,1) into v_register_p from apm_package_types
+ where package_key = register_p.package_key;
+ return v_register_p;
+ end register_p;
+
+ function 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
+ ) return apm_package_types.package_key%TYPE
+ is
+ begin
+ return apm.register_package(
+ package_key => register_application.package_key,
+ pretty_name => register_application.pretty_name,
+ pretty_plural => register_application.pretty_plural,
+ package_uri => register_application.package_uri,
+ package_type => 'apm_application',
+ singleton_p => register_application.singleton_p,
+ spec_file_path => register_application.spec_file_path,
+ spec_file_mtime => register_application.spec_file_mtime
+ );
+ end register_application;
+
+ procedure unregister_application (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_application.package_key,
+ cascade_p => unregister_application.cascade_p
+ );
+ end unregister_application;
+
+ function 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
+ ) return apm_package_types.package_key%TYPE
+ is
+ begin
+ return apm.register_package(
+ package_key => register_service.package_key,
+ pretty_name => register_service.pretty_name,
+ pretty_plural => register_service.pretty_plural,
+ package_uri => register_service.package_uri,
+ package_type => 'apm_service',
+ singleton_p => register_service.singleton_p,
+ spec_file_path => register_service.spec_file_path,
+ spec_file_mtime => register_service.spec_file_mtime
+ );
+ end register_service;
+
+ procedure unregister_service (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ begin
+ apm.unregister_package (
+ package_key => unregister_service.package_key,
+ cascade_p => unregister_service.cascade_p
+ );
+ end unregister_service;
+
+ -- 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
+ is
+ v_parameter_id apm_parameters.parameter_id%TYPE;
+ begin
+
+ v_parameter_id := acs_object.new(
+ object_id => parameter_id,
+ object_type => 'apm_parameter'
+ );
+ 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, register_parameter.description,
+ register_parameter.package_key, register_parameter.datatype,
+ register_parameter.default_value, register_parameter.section_name,
+ register_parameter.min_n_values, register_parameter.max_n_values);
+
+ return v_parameter_id;
+ -- XXX: create an attribute using the metadata system.
+
+ end register_parameter;
+
+ 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
+ is
+ begin
+ update apm_parameters
+ set parameter_name = nvl(update_parameter.parameter_name, parameter_name),
+ default_value = nvl(update_parameter.default_value, default_value),
+ datatype = nvl(update_parameter.datatype, datatype),
+ description = nvl(update_parameter.description, description),
+ section_name = nvl(update_parameter.section_name, section_name),
+ min_n_values = nvl(update_parameter.min_n_values, min_n_values),
+ max_n_values = nvl(update_parameter.max_n_values, max_n_values)
+ where parameter_id = update_parameter.parameter_id;
+ return parameter_id;
+ end;
+
+ function parameter_p(
+ package_key in apm_package_types.package_key%TYPE,
+ parameter_name in apm_parameters.parameter_name%TYPE
+ ) return integer
+ is
+ v_parameter_p integer;
+ begin
+ select decode(count(*),0,0,1) 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 parameter_p;
+
+ procedure unregister_parameter (
+ parameter_id in apm_parameters.parameter_id%TYPE
+ default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where parameter_id = unregister_parameter.parameter_id;
+ delete from apm_parameters
+ where parameter_id = unregister_parameter.parameter_id;
+ acs_object.delete(parameter_id);
+ end unregister_parameter;
+
+ function id_for_name (
+ parameter_name in apm_parameters.parameter_name%TYPE,
+ package_key in apm_parameters.package_key%TYPE
+ ) return apm_parameters.parameter_id%TYPE
+ is
+ 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 id_for_name;
+
+ 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
+ is
+ 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 get_value;
+
+ 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
+ is
+ 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(
+ parameter_id => v_parameter_id,
+ package_id => get_value.package_id
+ );
+ end get_value;
+
+
+ -- 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
+ )
+ is
+ 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
+ when NO_DATA_FOUND
+ then
+ v_value_id := apm_parameter_value.new(
+ package_id => package_id,
+ parameter_id => parameter_id,
+ attr_value => attr_value
+ );
+ end set_value;
+
+ 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
+ )
+ is
+ 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);
+ apm.set_value(
+ parameter_id => v_parameter_id,
+ package_id => set_value.package_id,
+ attr_value => set_value.attr_value
+ );
+ end set_value;
+end apm;
+/
+show errors
+
+create or replace package body apm_package
+as
+ procedure initialize_parameters (
+ package_id in apm_packages.package_id%TYPE,
+ package_key in apm_package_types.package_key%TYPE
+ )
+ is
+ v_value_id apm_parameter_values.value_id%TYPE;
+ cursor cur is
+ select parameter_id, default_value
+ from apm_parameters
+ where package_key = initialize_parameters.package_key;
+ begin
+ -- need to initialize all params for this type
+ for cur_val in cur
+ loop
+ v_value_id := apm_parameter_value.new(
+ package_id => initialize_parameters.package_id,
+ parameter_id => cur_val.parameter_id,
+ attr_value => cur_val.default_value
+ );
+ end loop;
+ end initialize_parameters;
+
+ 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
+ is
+ 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(
+ package_key => apm_package.new.package_key
+ );
+ v_num_instances := apm_package.num_instances(
+ package_key => apm_package.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 = apm_package.new.package_key;
+ return v_package_id;
+ else
+ v_package_id := acs_object.new(
+ object_id => package_id,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ if instance_name is null then
+ v_instance_name := package_key || ' ' || v_package_id;
+ else
+ v_instance_name := instance_name;
+ end if;
+
+ select package_type into v_package_type
+ from apm_package_types
+ where package_key = apm_package.new.package_key;
+
+ insert into apm_packages
+ (package_id, package_key, instance_name)
+ values
+ (v_package_id, 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;
+
+ initialize_parameters(
+ package_id => v_package_id,
+ package_key => apm_package.new.package_key
+ );
+ return v_package_id;
+
+ end if;
+end new;
+
+ procedure delete (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ cursor all_values is
+ select value_id from apm_parameter_values
+ where package_id = apm_package.delete.package_id;
+ cursor all_site_nodes is
+ select node_id from site_nodes
+ where object_id = apm_package.delete.package_id;
+ begin
+ -- Delete all parameters.
+ for cur_val in all_values loop
+ apm_parameter_value.delete(value_id => cur_val.value_id);
+ end loop;
+ delete from apm_applications where application_id = apm_package.delete.package_id;
+ delete from apm_services where service_id = apm_package.delete.package_id;
+ delete from apm_packages where package_id = apm_package.delete.package_id;
+ -- Delete the site nodes for the objects.
+ for cur_val in all_site_nodes loop
+ site_node.delete(cur_val.node_id);
+ end loop;
+ -- Delete the object.
+ acs_object.delete (
+ object_id => package_id
+ );
+ end delete;
+
+ function singleton_p (
+ package_key in apm_packages.package_key%TYPE
+ ) return integer
+ is
+ 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';
+ return v_singleton_p;
+
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end singleton_p;
+
+ function num_instances (
+ package_key in apm_package_types.package_key%TYPE
+ ) return integer
+ is
+ v_num_instances integer;
+ begin
+ select count(*) into v_num_instances
+ from apm_packages
+ where package_key = num_instances.package_key;
+ return v_num_instances;
+
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end num_instances;
+
+ function name (
+ package_id in apm_packages.package_id%TYPE
+ ) return varchar2
+ is
+ 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 name;
+
+ procedure enable (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ update apm_packages
+ set enabled_p = 't'
+ where package_id = enable.package_id;
+ end enable;
+
+ procedure disable (
+ package_id in apm_packages.package_id%TYPE
+ )
+ is
+ begin
+ update apm_packages
+ set enabled_p = 'f'
+ where package_id = disable.package_id;
+ end disable;
+
+ function highest_version (
+ package_key in apm_package_types.package_key%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ 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;
+ return v_version_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ return 0;
+ end highest_version;
+end apm_package;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ begin
+ if version_id is null then
+ select acs_object_id_seq.nextval
+ into v_version_id
+ from dual;
+ else
+ v_version_id := version_id;
+ end if;
+ v_version_id := acs_object.new(
+ object_id => version_id,
+ object_type => 'apm_package_version'
+ );
+ 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, package_key, version_name, version_uri,
+ summary, description_format, description,
+ release_date, vendor, vendor_uri,
+ installed_p, data_model_loaded_p);
+ return v_version_id;
+ end new;
+
+ procedure delete (
+ version_id in apm_packages.package_id%TYPE
+ )
+ is
+ v_package_key apm_package_types.package_key%TYPE;
+ v_num_versions integer;
+ begin
+ select package_key into v_package_key
+ from apm_package_versions
+ where version_id = apm_package_version.delete.version_id;
+ delete from apm_package_owners
+ where version_id = apm_package_version.delete.version_id;
+ delete from apm_package_files
+ where version_id = apm_package_version.delete.version_id;
+ delete from apm_package_dependencies
+ where version_id = apm_package_version.delete.version_id;
+ delete from apm_package_versions
+ where version_id = apm_package_version.delete.version_id;
+ acs_object.delete(apm_package_version.delete.version_id);
+ select count(*) into v_num_versions
+ from apm_package_versions
+ where package_key = v_package_key;
+ if v_num_versions = 0 then
+ apm.unregister_package(package_key => v_package_key);
+ end if;
+ end delete;
+
+ procedure enable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions set enabled_p = 't'
+ where version_id = enable.version_id;
+ end enable;
+
+ procedure disable (
+ version_id in apm_package_versions.version_id%TYPE
+ )
+ is
+ begin
+ update apm_package_versions
+ set enabled_p = 'f'
+ where version_id = disable.version_id;
+ end disable;
+
+
+ function copy(
+ version_id in apm_package_versions.version_id%TYPE,
+ new_version_id in apm_package_versions.version_id%TYPE default null,
+ new_version_name in apm_package_versions.version_name%TYPE,
+ new_version_uri in apm_package_versions.version_uri%TYPE
+ ) return apm_package_versions.version_id%TYPE
+ is
+ v_version_id integer;
+ begin
+ v_version_id := acs_object.new(
+ object_id => new_version_id,
+ object_type => 'apm_package_version'
+ );
+
+ 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 copy;
+
+ 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
+ is
+ v_version_id apm_package_versions.version_id%TYPE;
+ version_unchanged_p integer;
+ begin
+ -- Determine if version has changed.
+ select decode(count(*),0,0,1) 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 := copy(
+ version_id => edit.version_id,
+ new_version_id => edit.new_version_id,
+ new_version_name => edit.version_name,
+ new_version_uri => 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 = trunc(sysdate),
+ 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 edit;
+
+ 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
+ is
+ 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;
+ return v_file_id;
+ exception
+ when NO_DATA_FOUND
+ then
+ if file_id is null then
+ select acs_object_id_seq.nextval into v_file_id from dual;
+ else
+ v_file_id := 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);
+ return v_file_id;
+ end add_file;
+
+ -- 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
+ )
+ is
+ begin
+ delete from apm_package_files
+ where version_id = remove_file.version_id
+ and path = remove_file.path;
+ end remove_file;
+
+
+-- 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
+ is
+ 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 add_interface;
+
+ procedure remove_interface(
+ interface_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_interface.interface_id;
+ end remove_interface;
+
+ 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
+ )
+ is
+ 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;
+ remove_interface(v_dep_id);
+ end remove_interface;
+
+ -- 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
+ is
+ 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 add_dependency;
+
+ procedure remove_dependency(
+ dependency_id in apm_package_dependencies.dependency_id%TYPE
+ )
+ is
+ begin
+ delete from apm_package_dependencies
+ where dependency_id = remove_dependency.dependency_id;
+ end remove_dependency;
+
+
+ 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
+ )
+ is
+ 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;
+ remove_dependency(v_dep_id);
+ end remove_dependency;
+
+ function sortable_version_name (
+ version_name in apm_package_versions.version_name%TYPE
+ ) return varchar2
+ is
+ a_start integer;
+ a_end integer;
+ a_order varchar2(1000);
+ a_char char(1);
+ a_seen_letter char(1) := '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
+ raise_application_error(-20000, 'Expected number at position ' || a_start);
+ end if;
+ if a_end - a_start > 4 then
+ 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.';
+ elsif a_char = 'a' then
+ a_order := a_order || ' 1A.';
+ elsif a_char = 'b' then
+ a_order := a_order || ' 2B.';
+ else
+ -- uhoh... some wacky character. bomb
+ -- raise_application_error(-20000, 'Illegal character ''' || a_char ||
+ -- ' in version name ' || version_name || '''');
+ a_order := a_order || ' OD.';
+ end if;
+
+ -- can't have something like 3.3a1b2 - just one letter allowed!
+ if a_seen_letter = 't' then
+ 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 sortable_version_name;
+
+ function compare(
+ version_name_one in apm_package_versions.version_name%TYPE,
+ version_name_two in apm_package_versions.version_name%TYPE
+ ) return integer is
+ a_order_a varchar2(1000);
+ a_order_b varchar2(1000);
+ begin
+ a_order_a := sortable_version_name(version_name_one);
+ a_order_b := sortable_version_name(version_name_two);
+ if a_order_a < a_order_b then
+ return -1;
+ elsif a_order_a > a_order_b then
+ return 1;
+ end if;
+ return 0;
+ end compare;
+
+ 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
+ is
+ v_pos1 integer;
+ v_pos2 integer;
+ 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(v_path, instr(v_path, '/', -1) + 1);
+
+ -- Remove the extension, if it's .sql.
+ v_pos1 := instr(v_path, '.', -1);
+ 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 sortable_version_name(upgrade_p.initial_version_name) <= sortable_version_name(v_version_from) and
+ sortable_version_name(upgrade_p.final_version_name) >= sortable_version_name(v_version_to) then
+ return 1;
+ end if;
+
+ return 0;
+ exception when others then
+ -- Invalid version number.
+ return 0;
+ end upgrade_p;
+
+end apm_package_version;
+/
+show errors
+
+create or replace package body apm_package_type
+as
+ function 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
+ ) return apm_package_types.package_type%TYPE
+ is
+ 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 create_type.package_key;
+ end create_type;
+
+ 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
+ is
+ begin
+ UPDATE apm_package_types SET
+ pretty_name = nvl(update_type.pretty_name, pretty_name),
+ pretty_plural = nvl(update_type.pretty_plural, pretty_plural),
+ package_uri = nvl(update_type.package_uri, package_uri),
+ package_type = nvl(update_type.package_type, package_type),
+ spec_file_path = nvl(update_type.spec_file_path, spec_file_path),
+ spec_file_mtime = nvl(update_type.spec_file_mtime, spec_file_mtime),
+ singleton_p = nvl(update_type.singleton_p, singleton_p)
+ where package_key = update_type.package_key;
+ return update_type.package_key;
+ end update_type;
+
+ procedure drop_type (
+ package_key in apm_package_types.package_key%TYPE,
+ cascade_p in char default 'f'
+ )
+ is
+ cursor all_package_ids is
+ select package_id
+ from apm_packages
+ where package_key = drop_type.package_key;
+
+ cursor all_parameters is
+ select parameter_id from apm_parameters
+ where package_key = drop_type.package_key;
+ begin
+ if cascade_p = 't' then
+ for cur_val in all_package_ids
+ loop
+ apm_package.delete(
+ package_id => cur_val.package_id
+ );
+ end loop;
+ -- Unregister all parameters.
+ for cur_val in all_parameters
+ loop
+ apm.unregister_parameter(parameter_id => cur_val.parameter_id);
+ end loop;
+
+ end if;
+ delete from apm_package_types
+ where package_key = drop_type.package_key;
+ end drop_type;
+end apm_package_type;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_value_id apm_parameter_values.value_id%TYPE;
+ begin
+ v_value_id := acs_object.new(
+ object_id => value_id,
+ object_type => 'apm_parameter_value'
+ );
+ insert into apm_parameter_values
+ (value_id, package_id, parameter_id, attr_value)
+ values
+ (v_value_id, apm_parameter_value.new.package_id,
+ apm_parameter_value.new.parameter_id,
+ apm_parameter_value.new.attr_value);
+ return v_value_id;
+ end new;
+
+ procedure delete (
+ value_id in apm_parameter_values.value_id%TYPE default null
+ )
+ is
+ begin
+ delete from apm_parameter_values
+ where value_id = apm_parameter_value.delete.value_id;
+ acs_object.delete(value_id);
+ end delete;
+
+ end apm_parameter_value;
+/
+show errors;
+
+create or replace package body 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
+ is
+ v_application_id integer;
+ begin
+ v_application_id := apm_package.new (
+ package_id => application_id,
+ instance_name => instance_name,
+ package_key => package_key,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ return v_application_id;
+ end new;
+
+ procedure delete (
+ application_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+ delete from apm_applications
+ where application_id = apm_application.delete.application_id;
+ apm_package.delete(
+ package_id => application_id);
+ end delete;
+
+end;
+/
+show errors
+
+create or replace package body 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
+ is
+ v_service_id integer;
+ begin
+ v_service_id := apm_package.new (
+ package_id => service_id,
+ instance_name => instance_name,
+ package_key => package_key,
+ object_type => object_type,
+ creation_date => creation_date,
+ creation_user => creation_user,
+ creation_ip => creation_ip,
+ context_id => context_id
+ );
+ return v_service_id;
+ end new;
+
+ procedure delete (
+ service_id in acs_objects.object_id%TYPE
+ )
+ is
+ begin
+ delete from apm_services
+ where service_id = apm_service.delete.service_id;
+ apm_package.delete(
+ package_id => service_id
+ );
+ end delete;
+
+end;
+/
+show errors
+
+-- security stuff.
+
+drop trigger users_update_login_token;
+
+@@ security-drop.sql
+@@ security-create.sql
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 -r1.2 -r1.3
--- openacs-4/packages/acs-kernel/sql/postgresql/postgresql.sql 19 Mar 2001 05:07:08 -0000 1.2
+++ openacs-4/packages/acs-kernel/sql/postgresql/postgresql.sql 20 Mar 2001 22:51:56 -0000 1.3
@@ -1,5 +1,5 @@
+create view dual as select now() as sysdate;
-
create function instr(varchar,char,integer,integer) returns integer as '
declare
str alias for $1;
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test/acs-objects-test.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test/groups-test.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test/rel-constraints-test.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test/rel-segments-test-types-create.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test/rel-segments-test-types-drop.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test/rel-segments-test.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test-harness/acs-core.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/test-harness/acs-permissions.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.0-4.0.1.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.0.1-4.1b.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.0b2-4.0rc0.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.0rc0-4.0.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.1-4.1.1.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.1.1-4.2.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-4.1b-4.1.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-kernel/sql/upgrade/upgrade-beta-1-beta-2.sql'.
Fisheye: No comparison available. Pass `N' to diff?
Index: openacs-4/packages/acs-tcl/tcl/10-database-procs-oracle.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/Attic/10-database-procs-oracle.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-tcl/tcl/10-database-procs-oracle.tcl 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,366 @@
+ad_library {
+
+ Oracle-specific database API and utility procs
+
+ @creation-date 15 Apr 2000
+ @author Jon Salz (jsalz@arsdigita.com)
+ @cvs-id $Id: 10-database-procs-oracle.tcl,v 1.1 2001/03/20 22:51:56 donb Exp $
+}
+
+# DRB: The following two routines are an attempt to abstract the notion of
+# "NULL", since Oracle differs from SQL92-compliant RDBMS engines in
+# treating the empty string as a null. Unfortunately, they're implemented
+# naively and don't help. We'll keep them for now but eventually should
+# root out calls to them and replace them with the empty string.
+
+ad_proc -public db_null {} {
+ Represents the SQL keyword null
for use in SQL DML statements.
+} {
+ return ""
+}
+
+ad_proc -public db_nullify_empty_string { string } {
+ A convenience function that returns [db_null] if $string is the empty string.
+} {
+ if { [empty_string_p $string] } {
+ return [db_null]
+ } else {
+ return $string
+ }
+}
+
+proc_doc db_nextval { sequence } { Returns the next value for a sequence. This can utilize a pool of sequence values to save hits to the database. } {
+ return [db_string "nextval" "select $sequence.nextval from dual"]
+}
+
+proc_doc db_exec_plsql { statement_name sql args } {
+
+ Executes a PL/SQL statement, returning the variable of bind variable :1
.
+
+} {
+ ad_arg_parser { bind_output } $args
+ if { [info exists bind_output] } {
+ return -code error "the -bind_output switch is not currently supported"
+ }
+
+ db_with_handle db {
+ # Right now, use :1 as the output value if it occurs in the statement,
+ # or not otherwise.
+ if { [regexp {:1} $sql] } {
+ return [db_exec exec_plsql_bind $db $statement_name $sql 1 ""]
+ } else {
+ return [db_exec dml $db $statement_name $sql]
+ }
+ }
+}
+
+ad_proc -private db_exec { type db statement_name sql args } {
+
+ A helper procedure to execute a SQL statement, potentially binding
+ depending on the value of the $bind variable in the calling environment
+ (if set).
+
+} {
+ set start_time [clock clicks]
+
+ set errno [catch {
+ upvar bind bind
+ if { [info exists bind] && [llength $bind] != 0 } {
+ if { [llength $bind] == 1 } {
+ return [eval [list ns_ora $type $db -bind $bind $sql] $args]
+ } else {
+ set bind_vars [ns_set create]
+ foreach { name value } $bind {
+ ns_set put $bind_vars $name $value
+ }
+ return [eval [list ns_ora $type $db -bind $bind_vars $sql] $args]
+ }
+ } else {
+ return [uplevel 2 [list ns_ora $type $db $sql] $args]
+ }
+ } error]
+
+ ad_call_proc_if_exists ds_collect_db_call $db $type $statement_name $sql $start_time $errno $error
+ if { $errno == 2 } {
+ return $error
+ }
+
+ global errorInfo errorCode
+ return -code $errno -errorinfo $errorInfo -errorcode $errorCode $error
+}
+
+proc_doc db_dml { statement_name sql args } {
+ Do a DML statement.
+} {
+ ad_arg_parser { clobs blobs clob_files blob_files bind } $args
+
+ # Only one of clobs, blobs, clob_files, and blob_files is allowed.
+ # Remember which one (if any) is provided.
+ set lob_argc 0
+ set lob_argv [list]
+ set command "dml"
+ if { [info exists clobs] } {
+ set command "clob_dml"
+ set lob_argv $clobs
+ incr lob_argc
+ }
+ if { [info exists blobs] } {
+ set command "blob_dml"
+ set lob_argv $blobs
+ incr lob_argc
+ }
+ if { [info exists clob_files] } {
+ set command "clob_dml_file"
+ set lob_argv $clob_files
+ incr lob_argc
+ }
+ if { [info exists blob_files] } {
+ set command "blob_dml_file"
+ set lob_argv $blob_files
+ incr lob_argc
+ }
+ if { $lob_argc > 1 } {
+ error "Only one of -clobs, -blobs, -clob_files, or -blob_files may be specified as an argument to db_dml"
+ }
+ db_with_handle db {
+ if { $lob_argc == 1 } {
+ # Bind :1, :2, ..., :n as LOBs (where n = [llength $lob_argv])
+ set bind_vars [list]
+ for { set i 1 } { $i <= [llength $lob_argv] } { incr i } {
+ lappend bind_vars $i
+ }
+ eval [list db_exec "${command}_bind" $db $statement_name $sql $bind_vars] $lob_argv
+ } else {
+ eval [list db_exec $command $db $statement_name $sql] $lob_argv
+ }
+ }
+}
+
+proc_doc db_resultrows {} { Returns the number of rows affected by the last DML command. } {
+ global db_state
+ return [ns_ora resultrows $db_state(last_used)]
+}
+
+ad_proc db_continue_transaction {} {
+
+ If a transaction is set to be aborted, this procedure allows it to continue.
+ Intended for use only within a db_transaction on_error code block.
+} {
+ global db_state
+ db_with_handle db {
+ # The error has been handled, set the flag to false.
+ set db_state(db_abort_p,$db) 0
+ }
+}
+
+ad_proc db_write_clob { statement_name sql args } {
+ ad_arg_parser { bind } $args
+
+ db_with_handle db {
+ db_exec write_clob $db $statement_name $sql
+ }
+}
+
+ad_proc db_write_blob { statement_name sql args } {
+ ad_arg_parser { bind } $args
+
+ db_with_handle db {
+ db_exec write_blob $db $statement_name $sql
+ }
+}
+
+ad_proc db_blob_get_file { statement_name sql args } {
+ ad_arg_parser { bind file args } $args
+
+ db_with_handle db {
+ eval [list db_exec blob_get_file $db $statement_name $sql $file] $args
+ }
+}
+
+ad_proc db_get_sql_user { } {
+
+ Returns a valid user@database/password string to access a database through sqlplus.
+
+} {
+
+ set pool [lindex [nsv_get db_available_pools .] 0]
+ set datasource [ns_config ns/db/pool/$pool DataSource]
+ if { ![empty_string_p $datasource] && ![string is space $datasource] } {
+ return "[ns_config ns/db/pool/$pool User]/[ns_config ns/db/pool/$pool Password]@$datasource"
+ } else {
+ return "[ns_config ns/db/pool/$pool User]/[ns_config ns/db/pool/$pool Password]"
+ }
+}
+
+ad_proc db_source_sql_file { {-callback apm_ns_write_callback} file } {
+
+ Sources a SQL file (in SQL*Plus format).
+
+} {
+
+ global env
+ set user_pass [db_get_sql_user]
+ set fp [open "|[file join $env(ORACLE_HOME) bin sqlplus] $user_pass @$file" "r"]
+
+ while { [gets $fp line] >= 0 } {
+ # Don't bother writing out lines which are purely whitespace.
+ if { ![string is space $line] } {
+ apm_callback_and_log $callback "[ad_quotehtml $line]\n"
+ }
+ }
+ close $fp
+}
+
+
+ad_proc db_source_sqlj_file { {-callback apm_ns_write_callback} file } {
+
+ Sources a SQLJ file using loadjava.
+
+} {
+
+ global env
+ set user_pass [db_get_sql_user]
+ set fp [open "|[file join $env(ORACLE_HOME) bin loadjava] -verbose -user $user_pass $file" "r"]
+
+
+ # Despite the fact that this works, the text does not get written to the stream.
+ # The output is generated as an error when you attempt to close the input stream as
+ # done below.
+ while { [gets $fp line] >= 0 } {
+ # Don't bother writing out lines which are purely whitespace.
+ if { ![string is space $line] } {
+ apm_callback_and_log $callback "[ad_quotehtml $line]\n"
+ }
+ }
+ if { [catch {
+ close $fp
+ } errmsg] } {
+ apm_callback_and_log $callback "[ad_quotehtml $errmsg]\n"
+ }
+}
+
+ad_proc -public db_tables { -pattern } {
+ Returns a Tcl list of all the tables owned by the connected user.
+
+ @param pattern Will be used as LIKE 'pattern%' to limit the number of tables returned.
+
+ @author Lars Pind lars@pinds.com
+
+ @change-log yon@arsdigita.com 20000711 changed to return lower case table names
+} {
+ set tables [list]
+
+ if { [info exists pattern] } {
+ db_foreach table_names_with_pattern {
+ select lower(table_name) as table_name
+ from user_tables
+ where table_name like upper(:pattern)
+ } {
+ lappend tables $table_name
+ }
+ } else {
+ db_foreach table_names_without_pattern {
+ select lower(table_name) as table_name
+ from user_tables
+ } {
+ lappend tables $table_name
+ }
+ }
+ return $tables
+}
+
+
+ad_proc -public db_table_exists { table_name } {
+ Returns 1 if a table with the specified name exists in the database, otherwise 0.
+
+ @author Lars Pind (lars@pinds.com)
+} {
+ set n_rows [db_string table_count {
+ select count(*) from user_tables where table_name = upper(:table_name)
+ }]
+ return $n_rows
+}
+
+ad_proc -public db_columns { table_name } {
+ Returns a Tcl list of all the columns in the table with the given name.
+
+ @author Lars Pind lars@pinds.com
+
+ @change-log yon@arsdigita.com 20000711 changed to return lower case column names
+} {
+ set columns [list]
+ db_foreach table_column_names {
+ select lower(column_name) as column_name
+ from user_tab_columns
+ where table_name = upper(:table_name)
+ } {
+ lappend columns $column_name
+ }
+ return $columns
+}
+
+
+ad_proc -public db_column_exists { table_name column_name } {
+ Returns 1 if the row exists in the table, 0 if not.
+
+ @author Lars Pind lars@pinds.com
+} {
+ set columns [list]
+ set n_rows [db_string column_exists {
+ select count(*)
+ from user_tab_columns
+ where table_name = upper(:table_name)
+ and column_name = upper(:column_name)
+ }]
+ return [expr $n_rows > 0]
+}
+
+
+ad_proc -public db_column_type { table_name column_name } {
+
+ Returns the Oracle Data Type for the specified column.
+ Returns -1 if the table or column doesn't exist.
+
+ @author Yon Feldman (yon@arsdigita.com)
+
+ @change-log 10 July, 2000: changed to return error
+ if column name doesn't exist
+ (mdettinger@arsdigita.com)
+
+ @change-log 11 July, 2000: changed to return lower case data types
+ (yon@arsdigita.com)
+
+ @change-log 11 July, 2000: changed to return error using the db_string default clause
+ (yon@arsdigita.com)
+
+} {
+
+ return [db_string column_type_select "
+ select data_type as data_type
+ from user_tab_columns
+ where upper(table_name) = upper(:table_name)
+ and upper(column_name) = upper(:column_name)
+ " -default "-1"]
+
+}
+
+ad_proc -public ad_column_type { table_name column_name } {
+
+ Returns 'numeric' for number type columns, 'text' otherwise
+ Throws an error if no such column exists.
+
+ @author Yon Feldman (yon@arsdigita.com)
+
+} {
+
+ set column_type [db_column_type $table_name $column_name]
+
+ if { $column_type == -1 } {
+ return "Either table $table_name doesn't exist or column $column_name doesn't exist"
+ } elseif { [string compare $column_type "NUMBER"] } {
+ return "numeric"
+ } else {
+ return "text"
+ }
+
+}
Index: openacs-4/packages/acs-tcl/tcl/10-database-procs-postgresql.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/Attic/10-database-procs-postgresql.tcl,v
diff -u
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/acs-tcl/tcl/10-database-procs-postgresql.tcl 20 Mar 2001 22:51:56 -0000 1.1
@@ -0,0 +1,326 @@
+ad_library {
+
+ Postgres-specific database API and utility procs.
+
+ @creation-date 15 Apr 2000
+ @author Jon Salz (jsalz@arsdigita.com)
+ @cvs-id $Id: 10-database-procs-postgresql.tcl,v 1.1 2001/03/20 22:51:56 donb Exp $
+}
+
+proc_doc db_nextval { sequence } { Returns the next value for a sequence. This can utilize a pool of sequence values to save hits to the database. } {
+ return [db_string nextval "select nextval('$sequence')"]
+}
+
+proc_doc db_exec_plsql { statement_name sql args } {
+
+ Postgres doesn't have PL/SQL, of course, but it does have PL/pgSQL and
+ other procedural languages. Rather than assign the result to a bind
+ variable which is then returned to the caller, the Postgres version of
+ OpenACS requires the caller to perform a select query that returns
+ the value of the function.
+
+} {
+ ad_arg_parser { bind_output } $args
+ if { [info exists bind_output] } {
+ return -code error "the -bind_output switch is not currently supported"
+ }
+
+ db_with_handle db {
+ return [db_string $statement_name $sql]
+ }
+}
+
+ad_proc -private db_exec { type db statement_name sql args } {
+
+ A helper procedure to execute a SQL statement, potentially binding
+ depending on the value of the $bind variable in the calling environment
+ (if set).
+
+} {
+ set start_time [clock clicks]
+
+ set errno [catch {
+ upvar bind bind
+ if { [info exists bind] && [llength $bind] != 0 } {
+ if { [llength $bind] == 1 } {
+ return [eval [list ns_pg_bind $type $db -bind $bind $sql] $args]
+ } else {
+ set bind_vars [ns_set create]
+ foreach { name value } $bind {
+ ns_set put $bind_vars $name $value
+ }
+ return [eval [list ns_pg_bind $type $db -bind $bind_vars $sql] $args]
+ }
+ } else {
+ return [uplevel 2 [list ns_pg_bind $type $db $sql] $args]
+ }
+ } error]
+
+ ad_call_proc_if_exists ds_collect_db_call $db $type $statement_name $sql $start_time $errno $error
+ if { $errno == 2 } {
+ return $error
+ }
+
+ global errorInfo errorCode
+ return -code $errno -errorinfo $errorInfo -errorcode $errorCode $error
+}
+
+proc_doc db_dml { statement_name sql args } {
+ Do a DML statement. We don't have CLOBs in PG as PG 7.1 allows
+ unbounded compressed text columns. BLOBs are handled much differently,
+ to.
+} {
+ ad_arg_parser { bind } $args
+
+ db_with_handle db {
+ db_exec dml $db $statement_name $sql
+ }
+}
+
+proc_doc db_resultrows {} { Returns the number of rows affected by the last DML command. } {
+ global db_state
+ return [ns_pg ntuples $db_state(last_used)]
+}
+
+#ad_proc db_continue_transaction {} {
+#
+# If a transaction is set to be aborted, this procedure allows it to continue.
+# Intended for use only within a db_transaction on_error code block.
+#
+# DRB: we can't emulate this in Postgres. The best we can do is a COMMIT
+# followed by BEGIN. Commented out so caller will get an error.
+#
+#} {
+# global db_state
+# db_with_handle db {
+# # The error has been handled, set the flag to false.
+# set db_state(db_abort_p,$db) 0
+# }
+#}
+
+ad_proc db_write_clob { statement_name sql args } {
+ ad_arg_parser { bind } $args
+
+ db_with_handle db {
+ db_exec write_clob $db $statement_name $sql
+ }
+}
+
+ad_proc db_write_blob { statement_name sql args } {
+ ad_arg_parser { bind } $args
+
+ db_with_handle db {
+ db_exec write_blob $db $statement_name $sql
+ }
+}
+
+ad_proc db_blob_get_file { statement_name sql args } {
+ ad_arg_parser { bind file args } $args
+
+ db_with_handle db {
+ eval [list db_exec blob_get_file $db $statement_name $sql $file] $args
+ }
+}
+
+ad_proc db_get_pgbin { } {
+
+ Returns the database name from the first database pool. It assumes the
+ datasource is properly formatted since we've already verified that we
+ can connect to the pool.
+
+} {
+
+ set pool [lindex [nsv_get db_available_pools .] 0]
+ set driver [ns_config ns/db/pool/$pool Driver]
+ return [ns_config ns/db/driver/$driver pgbin]
+}
+
+ad_proc db_get_database { } {
+
+ Returns the database name from the first database pool. It assumes the
+ datasource is properly formatted since we've already verified that we
+ can connect to the pool.
+
+} {
+
+ set pool [lindex [nsv_get db_available_pools .] 0]
+ set datasource [ns_config ns/db/pool/$pool DataSource]
+ set last_colon_pos [string last ":" $datasource]
+ if { $last_colon_pos == -1 } {
+ ns_log Error "datasource contains no \":\"? datasource = $datasource"
+ return ""
+ }
+ return [string range $datasource [expr $last_colon_pos + 1] end]
+}
+
+ad_proc db_source_sql_file { {-callback apm_ns_write_callback} file } {
+
+ Sources a SQL file (in SQL*Plus format).
+
+} {
+
+ set fp [open "|[file join [db_get_pgbin] psql] [db_get_database] -f $file" "r"]
+
+ while { [gets $fp line] >= 0 } {
+ # Don't bother writing out lines which are purely whitespace.
+ if { ![string is space $line] } {
+ apm_callback_and_log $callback "[ad_quotehtml $line]\n"
+ }
+ }
+
+ # PSQL dumps errors and notice information on stderr, and has no option to turn
+ # this off. So we have to chug through the "error" lines looking for those that
+ # really signal an error.
+
+ set errno [ catch {
+ close $fp
+ } error]
+
+ if { $errno == 2 } {
+ return $error
+ }
+
+ # Just filter out the "NOTICE" lines, so we get the stack dump along with real
+ # ERRORs. This could be done with a couple of opaque-looking regexps...
+
+ set error_found 0
+ foreach line [split $error "\n"] {
+ if { [string first NOTICE $line] == -1 } {
+ append error_lines "$line\n"
+ set error_found [expr { $error_found || [string first ERROR $line] != -1 } ]
+ }
+ }
+
+ if { $error_found } {
+ global errorCode
+ return -code error -errorinfo $error_lines -errorcode $errorCode
+ }
+}
+
+ad_proc -public db_tables { -pattern } {
+ Returns a Tcl list of all the tables owned by the connected user.
+
+ @param pattern Will be used as LIKE 'pattern%' to limit the number of tables returned.
+
+ @author Don Baccus dhogaza@pacifier.com
+
+} {
+ set tables [list]
+
+ if { [info exists pattern] } {
+ db_foreach table_names_with_pattern {
+ select relname
+ from pg_class
+ where relname like lower(:pattern) and
+ relname !~ '^pg_' and relkind = 'r'
+ } {
+ lappend tables $relname
+ }
+ } else {
+ db_foreach table_names_without_pattern {
+ select relname
+ from pg_class
+ where relname !~ '^pg_' and relkind = 'r'
+ } {
+ lappend tables $relname
+ }
+ }
+ return $tables
+}
+
+ad_proc -public db_table_exists { table_name } {
+ Returns 1 if a table with the specified name exists in the database, otherwise 0.
+
+ @author Don Baccus dhogaza@pacifier.com
+
+} {
+ set n_rows [db_string table_count {
+ select count(*) from pg_class
+ where relname = lower(:table_name) and
+ relname !~ '^pg_' and relkind = 'r'
+ }]
+ return $n_rows
+}
+
+ad_proc -public db_columns { table_name } {
+ Returns a Tcl list of all the columns in the table with the given name.
+
+ @author Lars Pind lars@pinds.com
+
+ @change-log yon@arsdigita.com 20000711 changed to return lower case column names
+} {
+ set columns [list]
+ db_foreach table_column_names {
+ select lower(column_name) as column_name
+ from user_tab_columns
+ where table_name = upper(:table_name)
+ } {
+ lappend columns $column_name
+ }
+ return $columns
+}
+
+
+ad_proc -public db_column_exists { table_name column_name } {
+ Returns 1 if the row exists in the table, 0 if not.
+
+ @author Lars Pind lars@pinds.com
+} {
+ set columns [list]
+ set n_rows [db_string column_exists {
+ select count(*)
+ from user_tab_columns
+ where table_name = upper(:table_name)
+ and column_name = upper(:column_name)
+ }]
+ return [expr $n_rows > 0]
+}
+
+
+ad_proc -public db_column_type { table_name column_name } {
+
+ Returns the Oracle Data Type for the specified column.
+ Returns -1 if the table or column doesn't exist.
+
+ @author Yon Feldman (yon@arsdigita.com)
+
+ @change-log 10 July, 2000: changed to return error
+ if column name doesn't exist
+ (mdettinger@arsdigita.com)
+
+ @change-log 11 July, 2000: changed to return lower case data types
+ (yon@arsdigita.com)
+
+ @change-log 11 July, 2000: changed to return error using the db_string default clause
+ (yon@arsdigita.com)
+
+} {
+
+ return [db_string column_type_select "
+ select data_type as data_type
+ from user_tab_columns
+ where upper(table_name) = upper(:table_name)
+ and upper(column_name) = upper(:column_name)
+ " -default "-1"]
+
+}
+
+ad_proc -public ad_column_type { table_name column_name } {
+
+ Returns 'numeric' for number type columns, 'text' otherwise
+ Throws an error if no such column exists.
+
+ @author Yon Feldman (yon@arsdigita.com)
+
+} {
+
+ set column_type [db_column_type $table_name $column_name]
+
+ if { $column_type == -1 } {
+ return "Either table $table_name doesn't exist or column $column_name doesn't exist"
+ } elseif { [string compare $column_type "NUMBER"] } {
+ return "numeric"
+ } else {
+ return "text"
+ }
+}
Index: openacs-4/packages/acs-tcl/tcl/10-database-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/Attic/10-database-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/acs-tcl/tcl/10-database-procs.tcl 13 Mar 2001 22:59:26 -0000 1.1
+++ openacs-4/packages/acs-tcl/tcl/10-database-procs.tcl 20 Mar 2001 22:51:56 -0000 1.2
@@ -4,37 +4,21 @@
@creation-date 15 Apr 2000
@author Jon Salz (jsalz@arsdigita.com)
- @cvs-id $Id$
+ @cvs-id 10-database-procs.tcl,v 1.4.2.1 2000/11/20 18:23:12 brech Exp
}
-ad_proc -public db_null {} {
- Represents the SQL keyword null
for use in SQL DML statements.
+proc_doc db_type { } {
+ Returns the RDBMS type (i.e. oracle, postgresql) this OpenACS installation is
+ using. The nsv ad_database_type is set up during the bootstrap process.
} {
- # Oracle coerces the empty string into null, in DML.
- #
- return ""
+ return [nsv_get ad_database_type .]
}
-ad_proc -public db_nullify_empty_string { string } {
- A convenience function that returns [db_null] if $string is the empty string.
-} {
- if { [empty_string_p $string] } {
- return [db_null]
- } else {
- return $string
- }
-}
-
proc_doc db_quote { string } { Quotes a string value to be placed in a SQL statement. } {
regsub -all {'} "$string" {''} result
return $result
}
-proc_doc db_nextval { sequence } { Returns the next value for a sequence. } {
- return [db_string "nextval" "select $sequence.nextval from dual"]
-}
-
-
proc_doc db_nth_pool_name { n } {
Returns the name of the pool used for the nth-nested selection (0-relative).
} {
@@ -47,31 +31,6 @@
return $pool
}
-#
-# Initialize the list of available pools
-#
-
-global apm_first_time_loading_p
-if { [info exist apm_first_time_loading_p] && $apm_first_time_loading_p } {
- set server_name [ns_info server]
- append config_path "ns/server/$server_name/acs/database"
- set the_set [ns_configsection $config_path]
- set pools [list]
- if {![empty_string_p $the_set]} {
- for {set i 0} {$i < [ns_set size $the_set]} {incr i} {
- if { [ns_set key $the_set $i] == "AvailablePool" } {
- lappend pools [ns_set value $the_set $i]
- }
- }
- }
- if { [llength $pools] == 0 } {
- set pools [ns_db pools]
- }
- ns_log Notice "Database API: The following pools are available: $pools"
- nsv_set db_available_pools . $pools
-}
-
-
proc_doc db_with_handle { db code_block } {
Places a usable database handle in $db and executes $code_block.
@@ -138,27 +97,6 @@
}
}
-proc_doc db_exec_plsql { statement_name sql args } {
-
- Executes a PL/SQL statement, returning the variable of bind variable :1
.
-
-} {
- ad_arg_parser { bind_output } $args
- if { [info exists bind_output] } {
- return -code error "the -bind_output switch is not currently supported"
- }
-
- db_with_handle db {
- # Right now, use :1 as the output value if it occurs in the statement,
- # or not otherwise.
- if { [regexp {:1} $sql] } {
- return [db_exec exec_plsql_bind $db $statement_name $sql 1 ""]
- } else {
- return [db_exec dml $db $statement_name $sql]
- }
- }
-}
-
proc_doc db_release_unused_handles {} {
Releases any database handles that are presently unused.
@@ -205,41 +143,6 @@
return -code $errno -errorinfo $errorInfo -errorcode $errorCode $error
}
-ad_proc -private db_exec { type db statement_name sql args } {
-
- A helper procedure to execute a SQL statement, potentially binding
- depending on the value of the $bind variable in the calling environment
- (if set).
-
-} {
- set start_time [clock clicks]
-
- set errno [catch {
- upvar bind bind
- if { [info exists bind] && [llength $bind] != 0 } {
- if { [llength $bind] == 1 } {
- return [eval [list ns_ora $type $db -bind $bind $sql] $args]
- } else {
- set bind_vars [ns_set create]
- foreach { name value } $bind {
- ns_set put $bind_vars $name $value
- }
- return [eval [list ns_ora $type $db -bind $bind_vars $sql] $args]
- }
- } else {
- return [uplevel 2 [list ns_ora $type $db $sql] $args]
- }
- } error]
-
- ad_call_proc_if_exists ds_collect_db_call $db $type $statement_name $sql $start_time $errno $error
- if { $errno == 2 } {
- return $error
- }
-
- global errorInfo errorCode
- return -code $errno -errorinfo $errorInfo -errorcode $errorCode $error
-}
-
proc_doc db_string { statement_name sql args } {
Returns the first column of the result of the SQL query $sql.
@@ -511,58 +414,7 @@
}
}
-proc_doc db_dml { statement_name sql args } {
- Do a DML statement.
-} {
- ad_arg_parser { clobs blobs clob_files blob_files bind } $args
- # Only one of clobs, blobs, clob_files, and blob_files is allowed.
- # Remember which one (if any) is provided.
- set lob_argc 0
- set lob_argv [list]
- set command "dml"
- if { [info exists clobs] } {
- set command "clob_dml"
- set lob_argv $clobs
- incr lob_argc
- }
- if { [info exists blobs] } {
- set command "blob_dml"
- set lob_argv $blobs
- incr lob_argc
- }
- if { [info exists clob_files] } {
- set command "clob_dml_file"
- set lob_argv $clob_files
- incr lob_argc
- }
- if { [info exists blob_files] } {
- set command "blob_dml_file"
- set lob_argv $blob_files
- incr lob_argc
- }
- if { $lob_argc > 1 } {
- error "Only one of -clobs, -blobs, -clob_files, or -blob_files may be specified as an argument to db_dml"
- }
- db_with_handle db {
- if { $lob_argc == 1 } {
- # Bind :1, :2, ..., :n as LOBs (where n = [llength $lob_argv])
- set bind_vars [list]
- for { set i 1 } { $i <= [llength $lob_argv] } { incr i } {
- lappend bind_vars $i
- }
- eval [list db_exec "${command}_bind" $db $statement_name $sql $bind_vars] $lob_argv
- } else {
- eval [list db_exec $command $db $statement_name $sql] $lob_argv
- }
- }
-}
-
-proc_doc db_resultrows {} { Returns the number of rows affected by the last DML command. } {
- global db_state
- return [ns_ora resultrows $db_state(last_used)]
-}
-
ad_proc db_0or1row { statement_name sql args } {
Performs the SQL query $sql, setting variables to column values. Returns 1 if a row is returned, or 0 if no row is returned.
@@ -854,104 +706,24 @@
}
}
-ad_proc db_continue_transaction {} {
-
- If a transaction is set to be aborted, this procedure allows it to continue.
- Intended for use only within a db_transaction on_error code block.
-} {
- global db_state
- db_with_handle db {
- # The error has been handled, set the flag to false.
- set db_state(db_abort_p,$db) 0
- }
-}
+ad_proc -public db_name { } {
-ad_proc db_write_clob { statement_name sql args } {
- ad_arg_parser { bind } $args
+ Returns the name of the database as reported by the driver.
+} {
db_with_handle db {
- db_exec write_clob $db $statement_name $sql
+ set dbtype [ns_db dbtype $db]
}
+ return $dbtype
}
-ad_proc db_write_blob { statement_name sql args } {
- ad_arg_parser { bind } $args
+# NSV db_pooled_sequences($sequence) is the number of sequence values for the
+# sequence named $sequence that should be pooled.
+# NSV db_pooled_nextvals($sequence) is a list of available sequence values for
+# the sequence named $sequence. It is a ring buffer (values are added to the
+# end and popped from the beginning).
+# NSV db_pooled_nextvals(.mutex) is a mutex guarding the db_pooled_nextvals.
- db_with_handle db {
- db_exec write_blob $db $statement_name $sql
- }
-}
-
-ad_proc db_blob_get_file { statement_name sql args } {
- ad_arg_parser { bind file args } $args
-
- db_with_handle db {
- eval [list db_exec blob_get_file $db $statement_name $sql $file] $args
- }
-}
-
-ad_proc db_get_sql_user { } {
-
- Returns a valid user@database/password string to access a database through sqlplus.
-
-} {
-
- set pool [lindex [nsv_get db_available_pools .] 0]
- set datasource [ns_config ns/db/pool/$pool DataSource]
- if { ![empty_string_p $datasource] && ![string is space $datasource] } {
- return "[ns_config ns/db/pool/$pool User]/[ns_config ns/db/pool/$pool Password]@$datasource"
- } else {
- return "[ns_config ns/db/pool/$pool User]/[ns_config ns/db/pool/$pool Password]"
- }
-}
-
-ad_proc db_source_sql_file { {-callback apm_ns_write_callback} file } {
-
- Sources a SQL file (in SQL*Plus format).
-
-} {
-
- global env
- set user_pass [db_get_sql_user]
- set fp [open "|[file join $env(ORACLE_HOME) bin sqlplus] $user_pass @$file" "r"]
-
- while { [gets $fp line] >= 0 } {
- # Don't bother writing out lines which are purely whitespace.
- if { ![string is space $line] } {
- apm_callback_and_log $callback "[ad_quotehtml $line]\n"
- }
- }
- close $fp
-}
-
-
-ad_proc db_source_sqlj_file { {-callback apm_ns_write_callback} file } {
-
- Sources a SQLJ file using loadjava.
-
-} {
-
- global env
- set user_pass [db_get_sql_user]
- set fp [open "|[file join $env(ORACLE_HOME) bin loadjava] -verbose -user $user_pass $file" "r"]
-
-
- # Despite the fact that this works, the text does not get written to the stream.
- # The output is generated as an error when you attempt to close the input stream as
- # done below.
- while { [gets $fp line] >= 0 } {
- # Don't bother writing out lines which are purely whitespace.
- if { ![string is space $line] } {
- apm_callback_and_log $callback "[ad_quotehtml $line]\n"
- }
- }
- if { [catch {
- close $fp
- } errmsg] } {
- apm_callback_and_log $callback "[ad_quotehtml $errmsg]\n"
- }
-}
-
# global db_state(handles) is a list of handles that have been allocated.
#
# global db_state(n_handles_used) is the number of handles in this list that are
Index: openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.tcl 13 Mar 2001 22:59:26 -0000 1.1
+++ openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.tcl 20 Mar 2001 22:51:56 -0000 1.2
@@ -28,13 +28,19 @@
} {
# Obtain the id of the ACS Administration node.
+
+ # DRB: this used to say "and rownum = 1" to limit the return to a single row,
+ # but this is Oracle-specific. It surprises me that the author thinks
+ # that more than one site_node might have object_id equal to the package_id being
+ # selected, but there's no harm in forcing the query to only return a single row
+ # no matter what. Using "min()" is portable, at least...
+
return [db_string acs_admin_node_p {
- select node_id
+ select min(node_id)
from site_nodes
where object_id = (select package_id
from apm_packages
where package_key = 'acs-admin')
- and rownum = 1
} -default 0]
}
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-tcl/tcl/bootstrap.tcl'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-tcl/tcl/database-util-procs.tcl'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-tcl/tcl/installer-init.tcl'.
Fisheye: No comparison available. Pass `N' to diff?
Fisheye: Tag 1.2 refers to a dead (removed) revision in file `openacs-4/packages/acs-tcl/tcl/installer.tcl'.
Fisheye: No comparison available. Pass `N' to diff?
Index: openacs-4/tcl/0-acs-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/tcl/0-acs-init.tcl,v
diff -u -r1.1 -r1.2
--- openacs-4/tcl/0-acs-init.tcl 13 Mar 2001 22:59:26 -0000 1.1
+++ openacs-4/tcl/0-acs-init.tcl 20 Mar 2001 22:51:56 -0000 1.2
@@ -1,7 +1,7 @@
# /tcl/0-acs-init.tcl
#
# The very first file invoked when ACS is started up. Sources
-# /packages/acs-tcl/tcl/bootstrap.tcl.
+# /packages/acs-tcl/bootstrap/bootstrap.tcl.
#
# jsalz@mit.edu, 12 May 2000
#
@@ -13,7 +13,7 @@
nsv_set acs_properties root_directory $root_directory
ns_log "Notice" "Loading the ACS, rooted at $root_directory"
-set bootstrap_file "$root_directory/packages/acs-tcl/tcl/bootstrap.tcl"
+set bootstrap_file "$root_directory/packages/acs-tcl/bootstrap/bootstrap.tcl"
ns_log "Notice" "Sourcing $bootstrap_file"
if { [file isfile $bootstrap_file] } {