Index: openacs-4/packages/acs-kernel/acs-kernel.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/acs-kernel.info,v
diff -u -r1.17.2.3 -r1.17.2.4
--- openacs-4/packages/acs-kernel/acs-kernel.info	17 Dec 2002 10:22:50 -0000	1.17.2.3
+++ openacs-4/packages/acs-kernel/acs-kernel.info	11 Feb 2003 17:03:29 -0000	1.17.2.4
@@ -153,45 +153,45 @@
             <file type="data_model_upgrade" path="upgrade-3.4-4.0/user-group-types.sql"/>
         </files>
         <parameters>
-            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="PermissionCacheP"  default="0" description="Whether to cache permission_p calls.  Use with extreme caution.  Only direct permissions managed via the tcl api are properly handled and some packages modify permissions directly in the database and will not work properly when this is turned on" section_name="permissions"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CommunityMemberAdminURL"  default="/acs-admin/users/one" description="the URL of the admin community member page" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CommunityMemberURL"  default="/shared/community-member" description="the URL of the public community member page" section_name="system-information"/>
-            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="PrivacyControlEnabledP"  default="0" description="Whether we control privacy" section_name="privacy"/>
-            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="MaxSize"  default="200000" description="The size of the util_memoize cache, if using the ns_cache module." section_name="memoize"/>
-            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="SessionRenew"  default="300" description="How much time do we let elapse before renewing a session cookie? This should be less than SessionTimeout." section_name="security"/>
-            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="LoginExpirationTime"  default="600" description="The expiration time for the login page. This is needed to protect against browser cached passwords." section_name="security"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedAttribute"  default="title name" description="A space separated list of allowed attribute names, e.g. title, src, etc.. You probably want to avoid onMouseOver and the like." section_name="antispam"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedURLAttribute"  default="HREF" description="A space separated list of allowed attribute names, for which the attribute value should be interpreted as a URL. These attributes will then be checked for valid protocols, cf. the AllowedProtocol parameter. This is in addition to the attributes allowed by the AllowedAttribute parameter." section_name="antispam"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedProtocol"  default="http https ftp mailto" description="A space separated list of protocols that are valid in URLs checked by ad_page_contract" section_name="antispam"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="RegisterRestrictToSSLFilters"  default="1" description="Whether to process the RestrictToSSL paths per site node on startup which can be quite slow on a site with many nodes." section_name="security"/>
-            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="PerformanceModeP"  default="0" description="Setting this to 1 will tell the request processor to make the assumption that once a url is mapped to a file, that mapping never changes. This obviously would cause problems on a development system, but will improve performance on a production server." section_name="request-processor"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedTag"  default="B I P A LI OL UL EM BR TT STRONG BLOCKQUOTE CODE PRE FIRST_NAMES LAST_NAME EMAIL GROUP_NAME" description="A space separated list of all the HTML tags that people may use." section_name="antispam"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ForceHostP"  default="0" description="if a user provides a Host header which isn't this, redirect the user to this particular host. e.g., if yourservername.com and                                     www.yourservername.com point to the same IP, set this to 1 so cookies will be properly set." section_name="request-processor"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="EnableLoggingP"  default="1" description="log clustering events?" section_name="server-cluster"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CanonicalServer"  description="In the list of IPs above, which is the canonical (primary) server? If a port is not listed, we assume port 80." section_name="server-cluster"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ClusterPeerIP"  description="A space separated list of servers in the cluster. This server's IP may be included too." section_name="server-cluster"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ClusterAuthorizedIP"  description="A space separated list of which machines can issues requests (e.g., flushing) to the cluster. Can use glob matching notation (10.0.0.*)" section_name="server-cluster"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ClusterEnabledP"  default="0" description="is clustering enabled?" section_name="server-cluster"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemCommandPaths"  default="/usr/local/bin /usr/bin /bin /usr/sbin /sbin /usr/sbin" description="Directories that contain system commands, such as tar, wget, and gunzip" section_name="apm"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="InfoFilePermissionsMode"  default="0775" description="The default UNIX permissions to assign to the .info file when it is created." section_name="apm"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ExtensionPrecedence"  default="adp,tcl,html,jpg,gif" description="precedence for file extensions, e.g., 'tcl,adp,html' means 'serve a .tcl file if available, else an .adp file if available, else an .html file if available, else the first file available in alphabetical order. Comma-separated." section_name="request-processor"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemURLSection"  default="SYSTEM" description="URL sections exempt from Host header checks and security/session handling. (can specify an arbitrary number)." section_name="request-processor"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="LogDebugP"  default="0" description="log request-processor debug messages to the error log? very verbose." section_name="request-processor"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="DebugP"  default="0" description="save debugging information for developer support?" section_name="request-processor"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SessionSweepInterval"  default="3600" description="how often should we sweep for old stale sessions?" section_name="security"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SessionLifetime"  default="604800" description="how long after the last hit should we save information in the SessionLifetime table?" section_name="security"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SessionTimeout"  default="1200" description="for how long can a be session inactive before it times out? (in seconds)" section_name="security"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowPersistentLoginP"  default="1" description="do we allow persistent logins?" section_name="security"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="OutgoingSender"  default="somenerd@yourdomain.com" description="The email address that will sign outgoing alerts." section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="HostAdministrator"  default="somenerd@yourdomain.com" description="a person whom people can email with technical problems" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AdminOwner"  default="a-programmer@yourdomain.com" description="who signs the admin pages, e.g., a programmer who can fix/enhance them" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemURL"  default="http://yourdomain.com" description="URL to tell users to go to" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemOwner"  default="webmaster@yourdomain.com" description="who signs the average user-visible pages" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="PublisherName"  default="Yourdomain Network, Inc." description="for legal pages, full corporate entity" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemName"  default="yourdomain Network" description="the name of your system" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="HomeName"  default="Your Workspace" description="the name of the workspace link" section_name="system-information"/>
-            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="HomeURL"  default="/pvt/home" description="the URL of the workspace link" section_name="system-information"/>
             <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="RestrictErrorsToAdminsP"  default="1" description="Whether we show errors to adminstrators only"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="HomeURL"  default="/pvt/home" description="the URL of the workspace link" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="HomeName"  default="Your Workspace" description="the name of the workspace link" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemName"  default="yourdomain Network" description="the name of your system" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="PublisherName"  default="Yourdomain Network, Inc." description="for legal pages, full corporate entity" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemOwner"  default="webmaster@yourdomain.com" description="who signs the average user-visible pages" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemURL"  default="http://yourdomain.com" description="URL to tell users to go to" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AdminOwner"  default="a-programmer@yourdomain.com" description="who signs the admin pages, e.g., a programmer who can fix/enhance them" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="HostAdministrator"  default="somenerd@yourdomain.com" description="a person whom people can email with technical problems" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="OutgoingSender"  default="somenerd@yourdomain.com" description="The email address that will sign outgoing alerts." section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowPersistentLoginP"  default="1" description="do we allow persistent logins?" section_name="security"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SessionTimeout"  default="1200" description="for how long can a be session inactive before it times out? (in seconds)" section_name="security"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SessionLifetime"  default="604800" description="how long after the last hit should we save information in the SessionLifetime table?" section_name="security"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SessionSweepInterval"  default="3600" description="how often should we sweep for old stale sessions?" section_name="security"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="DebugP"  default="0" description="save debugging information for developer support?" section_name="request-processor"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="LogDebugP"  default="0" description="log request-processor debug messages to the error log? very verbose." section_name="request-processor"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemURLSection"  default="SYSTEM" description="URL sections exempt from Host header checks and security/session handling. (can specify an arbitrary number)." section_name="request-processor"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ExtensionPrecedence"  default="adp,tcl,html,jpg,gif" description="precedence for file extensions, e.g., 'tcl,adp,html' means 'serve a .tcl file if available, else an .adp file if available, else an .html file if available, else the first file available in alphabetical order. Comma-separated." section_name="request-processor"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="InfoFilePermissionsMode"  default="0775" description="The default UNIX permissions to assign to the .info file when it is created." section_name="apm"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="SystemCommandPaths"  default="/usr/local/bin /usr/bin /bin /usr/sbin /sbin /usr/sbin" description="Directories that contain system commands, such as tar, wget, and gunzip" section_name="apm"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ClusterEnabledP"  default="0" description="is clustering enabled?" section_name="server-cluster"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ClusterAuthorizedIP"  description="A space separated list of which machines can issues requests (e.g., flushing) to the cluster. Can use glob matching notation (10.0.0.*)" section_name="server-cluster"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ClusterPeerIP"  description="A space separated list of servers in the cluster. This server's IP may be included too." section_name="server-cluster"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CanonicalServer"  description="In the list of IPs above, which is the canonical (primary) server? If a port is not listed, we assume port 80." section_name="server-cluster"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="EnableLoggingP"  default="1" description="log clustering events?" section_name="server-cluster"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ForceHostP"  default="0" description="if a user provides a Host header which isn't this, redirect the user to this particular host. e.g., if yourservername.com and                                     www.yourservername.com point to the same IP, set this to 1 so cookies will be properly set." section_name="request-processor"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedTag"  default="B I P A LI OL UL EM BR TT STRONG BLOCKQUOTE CODE PRE FIRST_NAMES LAST_NAME EMAIL GROUP_NAME" description="A space separated list of all the HTML tags that people may use." section_name="antispam"/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="PerformanceModeP"  default="0" description="Setting this to 1 will tell the request processor to make the assumption that once a url is mapped to a file, that mapping never changes. This obviously would cause problems on a development system, but will improve performance on a production server." section_name="request-processor"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="RegisterRestrictToSSLFilters"  default="1" description="Whether to process the RestrictToSSL paths per site node on startup which can be quite slow on a site with many nodes." section_name="security"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedProtocol"  default="http https ftp mailto" description="A space separated list of protocols that are valid in URLs checked by ad_page_contract" section_name="antispam"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedURLAttribute"  default="HREF" description="A space separated list of allowed attribute names, for which the attribute value should be interpreted as a URL. These attributes will then be checked for valid protocols, cf. the AllowedProtocol parameter. This is in addition to the attributes allowed by the AllowedAttribute parameter." section_name="antispam"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AllowedAttribute"  default="title name" description="A space separated list of allowed attribute names, e.g. title, src, etc.. You probably want to avoid onMouseOver and the like." section_name="antispam"/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="LoginExpirationTime"  default="600" description="The expiration time for the login page. This is needed to protect against browser cached passwords." section_name="security"/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="SessionRenew"  default="300" description="How much time do we let elapse before renewing a session cookie? This should be less than SessionTimeout." section_name="security"/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="MaxSize"  default="200000" description="The size of the util_memoize cache, if using the ns_cache module." section_name="memoize"/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="PrivacyControlEnabledP"  default="0" description="Whether we control privacy" section_name="privacy"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CommunityMemberURL"  default="/shared/community-member" description="the URL of the public community member page" section_name="system-information"/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CommunityMemberAdminURL"  default="/acs-admin/users/one" description="the URL of the admin community member page" section_name="system-information"/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="PermissionCacheP"  default="0" description="Whether to cache permission_p calls.  Use with extreme caution.  Only direct permissions managed via the tcl api are properly handled and some packages modify permissions directly in the database and will not work properly when this is turned on" section_name="permissions"/>
         </parameters>
 
     </version>
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql,v
diff -u -r1.6.4.2 -r1.6.4.3
--- openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql	21 Jan 2003 13:46:20 -0000	1.6.4.2
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-create.sql	11 Feb 2003 17:04:24 -0000	1.6.4.3
@@ -20,46 +20,6 @@
  objects like the site-wide organization, and the all users party.
 ';
 
--- create or replace package acs
--- as
--- 
---   function add_user (
---     user_id		in users.user_id%TYPE default null,
---     object_type		in acs_objects.object_type%TYPE
--- 	 		   default 'user',
---     creation_date	in acs_objects.creation_date%TYPE
--- 			   default sysdate,
---     creation_user	in acs_objects.creation_user%TYPE
--- 			   default null,
---     creation_ip		in acs_objects.creation_ip%TYPE default null,
---     email		in parties.email%TYPE,
---     url			in parties.url%TYPE default null,
---     first_names		in persons.first_names%TYPE,
---     last_name		in persons.last_name%TYPE,
---     password		in users.password%TYPE,
---     salt		in users.salt%TYPE,
---     password_question   in users.password_question%TYPE default null,
---     password_answer	in users.password_answer%TYPE default null,
---     screen_name		in users.screen_name%TYPE default null,
---     email_verified_p 	in users.email_verified_p%TYPE default 't',
---     member_state	in membership_rels.member_state%TYPE default 'approved'
---   )
---   return users.user_id%TYPE;
--- 
---   procedure remove_user (
---     user_id	in users.user_id%TYPE
---   );
--- 
---   function magic_object_id (
---      name	in acs_magic_objects.name%TYPE
---   ) return acs_objects.object_id%TYPE;
--- 
--- end acs;
-
--- show errors
-
--- create or replace package body acs
--- function add_user
 create function acs__add_user (integer,varchar,timestamp with time zone,integer,varchar,varchar,varchar,varchar,varchar,char,char,varchar,varchar,varchar,boolean,varchar)
 returns integer as '
 declare
@@ -113,8 +73,6 @@
    
 end;' language 'plpgsql';
 
-
--- procedure remove_user
 create function acs__remove_user (integer)
 returns integer as '
 declare
@@ -126,8 +84,6 @@
     return 0; 
 end;' language 'plpgsql';
 
-
--- function magic_object_id
 create function acs__magic_object_id (varchar)
 returns integer as '
 declare
@@ -143,10 +99,6 @@
    
 end;' language 'plpgsql' with(isstrict,iscachable);
 
-
-
--- show errors
-
 -- ******************************************************************
 -- * Community Core API
 -- ******************************************************************
@@ -189,7 +141,7 @@
 begin
   
   root_id := acs_object__new (
-    0,
+    -4,
     ''acs_object'',
     now(),
     null,
@@ -200,7 +152,7 @@
   insert into acs_magic_objects
    (name, object_id)
   values
-   (''security_context_root'', 0);
+   (''security_context_root'', -4);
 
 
   return root_id;
@@ -230,64 +182,92 @@
  -- Administrators can read, write, create, and delete. -- 
  ---------------------------------------------------------
 
- -- temporarily drop this trigger to avoid a data-change violation 
- -- on acs_privilege_hierarchy_index while updating the child privileges.
-
- drop trigger acs_priv_hier_ins_del_tr on acs_privilege_hierarchy;
-
  select acs_privilege__add_child('admin', 'read');
  select acs_privilege__add_child('admin', 'write');
  select acs_privilege__add_child('admin', 'create');
-
- -- re-enable the trigger before the last insert to force the 
- -- acs_privilege_hierarchy_index table to be updated.
-
- create trigger acs_priv_hier_ins_del_tr after insert or delete
- on acs_privilege_hierarchy for each row
- execute procedure acs_priv_hier_ins_del_tr ();
-
  select acs_privilege__add_child('admin', 'delete');
 
 end;
 
+-- Now create our special groups and users.   We can not create the
+-- relationships between these entities yet.  This is done in acs-install.sql
 
--- show errors
-
 create function inline_2 ()
 returns integer as '
 declare
   v_object_id integer;
 begin
 
- insert into acs_objects
-  (object_id, object_type)
- values
-  (-1, ''party'');
+  -- Make an "Unregistered Visitor" as object 0, which corresponds
+  -- with the user_id assigned throughout the toolkit Tcl code
 
- insert into parties
-  (party_id)
- values
-  (-1);
+  insert into acs_objects
+    (object_id, object_type)
+  values
+    (0, ''person'');
 
- insert into acs_magic_objects
-  (name, object_id)
- values
-  (''the_public'', -1);
+  insert into parties
+    (party_id)
+  values
+    (0);
 
+  insert into persons
+    (person_id, first_names, last_name)
+  values
+    (0, ''Unregistered'', ''Visitor'');
+
+  insert into acs_magic_objects
+    (name, object_id)
+  values
+    (''unregistered_visitor'', 0);
+
+  v_object_id := acs_group__new (
+    -1,
+    ''group'',
+    now(),
+    null,
+    null,
+    null,
+    null,
+    ''The Public'',
+    null,
+    null
+  );
+
+  insert into acs_magic_objects
+   (name, object_id)
+  values
+   (''the_public'', -1);
+
+  -- Add our only user, the Unregistered Visitor, to The Public
+  -- group.
+
+  perform membership_rel__new (
+    null,
+    ''membership_rel'',
+    acs__magic_object_id(''the_public''),      
+    acs__magic_object_id(''unregistered_visitor''),
+    ''approved'',
+    null,
+    null);
+
   return 0;
+
 end;' language 'plpgsql';
 
 select inline_2 ();
 
 drop function inline_2 ();
 
-
 create function inline_3 ()
 returns integer as '
 declare
   group_id integer;
 begin
 
+  -- We will create the registered users group with type group for the moment
+  -- because the application_group package has not yet been created.
+
   group_id := acs_group__new (
     -2,
     ''group'',
@@ -301,19 +281,29 @@
     null
   );
 
- insert into acs_magic_objects
-  (name, object_id)
- values
-  (''registered_users'', -2);
+  insert into acs_magic_objects
+   (name, object_id)
+  values
+   (''registered_users'', -2);
 
+  -- Now declare "The Public" to be composed of itself and the "Registered
+  -- Users" group
+
+  perform composition_rel__new (
+    null,
+    ''composition_rel'',
+    acs__magic_object_id(''the_public''),
+    acs__magic_object_id(''registered_users''),
+    null,
+    null);
+
   return 0;
 end;' language 'plpgsql';
 
 select inline_3 ();
 
 drop function inline_3 ();
 
- 
 select acs_object__new (
     -3,
     'acs_object',
@@ -323,10 +313,7 @@
     null
   );
 
- insert into acs_magic_objects
+insert into acs_magic_objects
   (name, object_id)
- values
+values
   ('default_context', -3);
-                  
-                  
--- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql,v
diff -u -r1.9.4.1 -r1.9.4.2
--- openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql	21 Jan 2003 17:34:57 -0000	1.9.4.1
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-install.sql	11 Feb 2003 17:04:24 -0000	1.9.4.2
@@ -48,6 +48,29 @@
 	       );
 
 
+  insert into application_groups
+    (group_id, package_id)
+  values
+    (-2, main_site_id);
+
+  update acs_objects
+  set object_type = ''application_group''
+  where object_id = -2;
+
+  perform rel_segment__new(
+                   null,
+                   ''rel_segment'',
+                   now(),
+                   null,
+                   null,
+                   null,
+                   null,
+                   ''Main Site Members'',
+                   -2,
+                   ''membership_rel'',
+                   null
+                 );
+
   PERFORM apm_package__enable (main_site_id); 
 
   node_id := site_node__new (
@@ -116,7 +139,6 @@
     null
   );
 
-
   cr_id := apm_service__new (
       null,
       ''ACS Content Repository'',
@@ -176,23 +198,6 @@
 
   PERFORM apm_package__enable (api_doc_id);
 
-  insert into inline_data (id,name) values (api_doc_id, ''api_doc_id'');
-
-  return null;
-
-end;' language 'plpgsql';
-
-  
-  -- Set default permissions for ACS API Browser so 
-  -- that only users logged in can view it
-create function inline_1 () returns integer as '
-declare
-        api_doc_id      integer;
-begin
-
-  select id into api_doc_id 
-  from inline_data where name = ''api_doc_id'';
-
   PERFORM acs_permission__grant_permission (
     api_doc_id, 
     acs__magic_object_id (''registered_users''), 
@@ -210,26 +215,15 @@
     null
     );
 
-    return null;
+  update acs_objects
+  set security_inherit_p = ''f''
+  where object_id = api_doc_id;
 
+  return null;
+
 end;' language 'plpgsql';
 
-create table inline_data (
-       id        integer,
-       name      varchar
-);
-
 select inline_0 ();
 
-select id from inline_data where name = 'api_doc_id';
-update acs_objects
-     set security_inherit_p = 'f'
-   where object_id = (select id from inline_data where name = 'api_doc_id');
-
-select inline_1 ();
-
 drop function inline_0 ();
-drop function inline_1 ();
-drop table inline_data;
 
--- show errors
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql,v
diff -u -r1.35.2.1 -r1.35.2.2
--- openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql	21 Jan 2003 13:46:20 -0000	1.35.2.1
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-objects-create.sql	11 Feb 2003 17:04:24 -0000	1.35.2.2
@@ -381,7 +381,9 @@
    from acs_object_context_index
    where object_id != ancestor_id;
 
-create function acs_objects_context_id_in_tr () returns opaque as '
+create or replace function acs_objects_context_id_in_tr () returns opaque as '
+declare
+        security_context_root integer;
 begin
   insert into acs_object_context_index
    (object_id, ancestor_id, n_generations)
@@ -396,13 +398,15 @@
      n_generations + 1 as n_generations
     from acs_object_context_index
     where object_id = new.context_id;
-  else if new.object_id != 0 then
-    -- 0 is the id of the security context root object
-    insert into acs_object_context_index
-     (object_id, ancestor_id, n_generations)
-    values
-     (new.object_id, 0, 1);
-  end if; end if;
+  else
+    security_context_root = acs__magic_object_id(''security_context_root'');
+    if new.object_id != security_context_root then
+      insert into acs_object_context_index
+        (object_id, ancestor_id, n_generations)
+      values
+        (new.object_id, security_context_root, 1);
+    end if;
+  end if;
 
   return new;
 
@@ -411,11 +415,10 @@
 create trigger acs_objects_context_id_in_tr after insert on acs_objects
 for each row execute procedure acs_objects_context_id_in_tr ();
 
--- show errors
-
-create function acs_objects_context_id_up_tr () returns opaque as '
+create or replace function acs_objects_context_id_up_tr () returns opaque as '
 declare
         pair    record;
+        security_context_root integer;
 begin
   if new.object_id = old.object_id and
      new.context_id = old.context_id and
@@ -455,19 +458,22 @@
       from acs_object_context_index
       where object_id = new.context_id;
     end loop;
-  else if new.object_id != 0 then
+  else
+    security_context_root = acs__magic_object_id(''security_context_root'');
+    if new.object_id != security_context_root then
     -- We need to make sure that new.OBJECT_ID and all of its
-    -- children have 0 as an ancestor.
+    -- children have security_context_root as an ancestor.
     for pair in  select *
 		 from acs_object_context_index
 		 where ancestor_id = new.object_id 
-    LOOP
-      insert into acs_object_context_index
-       (object_id, ancestor_id, n_generations)
-      values
-       (pair.object_id, 0, pair.n_generations + 1);
-    end loop;
-  end if; end if;
+      LOOP
+        insert into acs_object_context_index
+         (object_id, ancestor_id, n_generations)
+        values
+         (pair.object_id, security_context_root, pair.n_generations + 1);
+      end loop;
+    end if;
+  end if;
 
   return new;
 
Index: openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql,v
diff -u -r1.19 -r1.19.4.1
--- openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql	8 Dec 2001 01:17:59 -0000	1.19
+++ openacs-4/packages/acs-kernel/sql/postgresql/acs-permissions-create.sql	11 Feb 2003 17:04:24 -0000	1.19.4.1
@@ -69,7 +69,26 @@
 create index priv_hier_sortkey_idx on 
 acs_privilege_hierarchy_index (tree_sortkey);
 
+-- Added table to materialize view that previously used 
+-- acs_privilege_descendant_map name
+--
+-- DanW (dcwickstrom@earthlink.net) 30 Jan, 2003
 
+create table acs_privilege_descendant_map (
+	privilege       varchar(100) not null 
+                        constraint acs_priv_hier_priv_fk
+			references acs_privileges (privilege),
+        descendant      varchar(100) not null 
+                        constraint acs_priv_hier_child_priv_fk
+			references acs_privileges (privilege)
+
+);
+
+-- DRB: Empirical testing showed that even with just 61 entries in the new table
+-- this index sped things up by roughly 15%
+
+create index acs_priv_desc_map_idx on acs_privilege_descendant_map(descendant);
+
 -- This trigger is used to create a pseudo-tree hierarchy that
 -- can be used to emulate tree queries on the acs_privilege_hierarchy table.
 -- The acs_privilege_hierarchy table maintains the permissions structure, but 
@@ -110,13 +129,14 @@
 -- This would be better, since the same query could be used for both oracle
 -- and postgresql.
 
-create function acs_priv_hier_ins_del_tr () returns opaque as '
+create or replace function acs_priv_hier_ins_del_tr () returns opaque as '
 declare
         new_value       integer;
         new_key         varbit default null;
         v_rec           record;
         deleted_p       boolean;
 begin
+
         -- if more than one node was deleted the second trigger call
         -- will error out.  This check avoids that problem.
 
@@ -166,6 +186,13 @@
 
         end LOOP;
 
+        -- materialize the map view to speed up queries
+        -- DanW (dcwickstrom@earthlink.net) 30 Jan, 2003
+        delete from acs_privilege_descendant_map;
+
+        insert into acs_privilege_descendant_map (privilege, descendant) 
+        select privilege, descendant from acs_privilege_descendant_map_view;
+
         return new;
 
 end;' language 'plpgsql';
@@ -353,7 +380,12 @@
 create index acs_permissions_grantee_idx on acs_permissions (grantee_id);
 create index acs_permissions_privilege_idx on acs_permissions (privilege);
 
-create view acs_privilege_descendant_map
+-- Added table to materialize view that previously used 
+-- acs_privilege_descendant_map name
+--
+-- DanW (dcwickstrom@earthlink.net) 30 Jan, 2003
+
+create view acs_privilege_descendant_map_view
 as select p1.privilege, p2.privilege as descendant
    from acs_privileges p1, acs_privileges p2
    where exists (select h2.child_privilege
@@ -376,81 +408,18 @@
    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.
+-- New fast version of acs_object_party_privilege_map
 
-create view acs_object_party_privilege_map
-as select ogpm.object_id, gmm.member_id as party_id, ogpm.privilege
-   from acs_object_grantee_priv_map ogpm, group_approved_member_map gmm
-   where ogpm.grantee_id = gmm.group_id
-   union
-   select ogpm.object_id, rsmm.member_id as party_id, ogpm.privilege
-   from acs_object_grantee_priv_map ogpm, rel_seg_approved_member_map rsmm
-   where ogpm.grantee_id = rsmm.segment_id
-   union
-   select object_id, grantee_id as party_id, privilege
-   from acs_object_grantee_priv_map
-   union
-   select object_id, u.user_id as party_id, privilege
-   from acs_object_grantee_priv_map m, users u
-   where m.grantee_id = -1
-   union
-   select object_id, 0 as party_id, privilege
-   from acs_object_grantee_priv_map
-   where grantee_id = -1;
+create view acs_object_party_privilege_map as
+select c.object_id, pdm.descendant as privilege, pamm.member_id as party_id
+from acs_object_context_index c, acs_permissions p, acs_privilege_descendant_map pdm,
+  party_approved_member_map pamm
+where c.ancestor_id = p.object_id
+  and pdm.privilege = p.privilege
+  and pamm.party_id = p.grantee_id;
 
-----------------------------------------------------
--- ALTERNATE VIEW: ALL_OBJECT_PARTY_PRIVILEGE_MAP --
-----------------------------------------------------
-
--- This view is a helper for all_object_party_privilege_map
-create view acs_grantee_party_map as
-   select -1 as grantee_id, 0 as party_id from dual
-   union all
-   select -1 as grantee_id, user_id as party_id
-   from users
-   union all
-   select party_id as grantee_id, party_id
-   from parties
-   union all
-   select segment_id as grantee_id, member_id
-   from rel_seg_approved_member_map
-   union all
-   select group_id as grantee_id, member_id as party_id
-   from group_approved_member_map;
-
--- This view is like acs_object_party_privilege_map, but does not 
--- necessarily return distinct rows.  It may be *much* faster to join
--- against this view instead of acs_object_party_privilege_map, and is
--- usually not much slower.  The tradeoff for the performance boost is
--- increased complexity in your usage of the view.  Example usage that I've
--- found works well is:
---
---    select DISTINCT 
---           my_table.*
---    from my_table,
---         (select object_id
---          from all_object_party_privilege_map 
---          where party_id = :user_id and privilege = :privilege) oppm
---    where oppm.object_id = my_table.my_id;
---
-
--- DRB: This view does seem to be quite fast in Postgres as well as Oracle.
-
 create view all_object_party_privilege_map as
-select         op.object_id,
-               pdm.descendant as privilege,
-               gpm.party_id as party_id
-        from acs_object_paths op, 
-             acs_permissions p, 
-             acs_privilege_descendant_map pdm,
-             acs_grantee_party_map gpm
-        where op.ancestor_id = p.object_id 
-          and pdm.privilege = p.privilege
-          and gpm.grantee_id = p.grantee_id;
+select * from acs_object_party_privilege_map;
 
 
 -- This table acts as a mutex for inserts/deletes from acs_permissions.
@@ -530,124 +499,23 @@
     return 0; 
 end;' language 'plpgsql';
 
--- Speedy version of permission_p from Matthew Avalos
--- Further improved to a minor degree by Don Baccus
+-- Really speedy version of permission_p written by Don Baccus
 
-create function acs_permission__permission_p (integer,integer,varchar)
+create or replace function acs_permission__permission_p (integer,integer,varchar)
 returns boolean as '
 declare
     permission_p__object_id           alias for $1;
     permission_p__party_id            alias for $2;
     permission_p__privilege           alias for $3;
     exists_p                          boolean;
 begin
-    --
-    -- Check public-like permissions
-    if (0 = permission_p__party_id or
-        exists (select 1 from users where user_id = permission_p__party_id)) and
-        exists (select 1
-                from acs_object_grantee_priv_map
-                where object_id = permission_p__object_id
-                  and privilege = permission_p__privilege
-                  and grantee_id = -1)
-    --
-    then
-       return ''t'';
-    end if;
-    --
-    -- Check direct permissions
-    if exists (
-        select 1
-          from acs_object_grantee_priv_map
-         where object_id = permission_p__object_id
-           and grantee_id = permission_p__party_id
-           and privilege = permission_p__privilege)
-    then
-        return ''t'';
-    end if;
-    --
-    -- Check group permmissions
-    if exists (
-          select 1
-          from acs_object_grantee_priv_map ogpm,
-               group_approved_member_map gmm
-         where object_id = permission_p__object_id
-           and gmm.member_id = permission_p__party_id
-           and privilege = permission_p__privilege
-           and ogpm.grantee_id = gmm.group_id)
-    then
-        return ''t'';
-    end if;
-    --
-    -- relational segment approved group
-    if exists (
-        select 1
-          from acs_object_grantee_priv_map ogpm,
-               rel_seg_approved_member_map rsmm
-         where object_id = permission_p__object_id
-           and rsmm.member_id = permission_p__party_id
-           and privilege = permission_p__privilege
-           and ogpm.grantee_id = rsmm.segment_id)
-    then
-        return ''t'';
-    end if;
-    return ''f'';
+  return exists (select 1
+                 from acs_permissions p, party_approved_member_map m,
+                   acs_object_context_index c, acs_privilege_descendant_map h
+                 where p.object_id = c.ancestor_id
+                   and h.descendant = permission_p__privilege
+                   and c.object_id = permission_p__object_id
+                   and m.member_id = permission_p__party_id
+                   and p.privilege = h.privilege
+                   and p.grantee_id = m.party_id);
 end;' language 'plpgsql';
-
--- Returns true if at least one user exists with the given permission.  Used
--- to avoid some queries on acs_object_party_privilege_map.
-
-create function acs_permission__user_with_perm_exists_p (integer,varchar)
-returns boolean as '
-declare
-    permission_p__object_id           alias for $1;
-    permission_p__privilege           alias for $2;
-begin
-    --
-    -- Check public-like permissions
-    if exists (select 1
-               from acs_object_grantee_priv_map
-                where object_id = permission_p__object_id
-                  and privilege = permission_p__privilege
-                  and grantee_id = -1)
-    --
-    then
-       return ''t'';
-    end if;
-    --
-    -- Check direct user permissions
-    if exists (
-        select 1
-          from acs_object_grantee_priv_map, users
-         where object_id = permission_p__object_id
-           and grantee_id = user_id
-           and privilege = permission_p__privilege)
-    then
-        return ''t'';
-    end if;
-    --
-    -- Check group permmissions
-    if exists (
-          select 1
-          from acs_object_grantee_priv_map ogpm,
-               group_approved_member_map gmm
-         where object_id = permission_p__object_id
-           and privilege = permission_p__privilege
-           and ogpm.grantee_id = gmm.group_id)
-    then
-        return ''t'';
-    end if;
-    --
-    -- relational segment approved group
-    if exists (
-        select 1
-          from acs_object_grantee_priv_map ogpm,
-               rel_seg_approved_member_map rsmm
-         where object_id = permission_p__object_id
-           and privilege = permission_p__privilege
-           and ogpm.grantee_id = rsmm.segment_id)
-    then
-        return ''t'';
-    end if;
-    return ''f'';
-end;' language 'plpgsql';
Index: openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql,v
diff -u -r1.16.2.1 -r1.16.2.2
--- openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql	21 Jan 2003 13:46:20 -0000	1.16.2.1
+++ openacs-4/packages/acs-kernel/sql/postgresql/groups-body-create.sql	11 Feb 2003 17:04:24 -0000	1.16.2.2
@@ -9,11 +9,154 @@
 --------------
 -- TRIGGERS --
 --------------
--- a dummy trigger was defined in groups-create.sql
-drop trigger membership_rels_in_tr on membership_rels;
-drop function membership_rels_in_tr ();
-create function membership_rels_in_tr () returns opaque as '
+
+-- DRB: Helper functions to maintain the materialized party_approved_member_map.  The counting crap
+-- has to do with the way composition_rels work, which is not how any sane person would care
+-- for them to work.   Fixing the groups and relational segments model will be a nice future project.
+-- For now I will just settle for making permission checking fast ...
+
+create or replace function insert_into_party_map(integer, integer, varchar) returns integer as '
 declare
+  p_party_id alias for $1;
+  p_member_id alias for $2;
+  p_rel_type alias for $3;
+  v_segment_id rel_segments.segment_id%TYPE;
+  v_count integer;
+begin
+
+  insert into party_approved_member_map
+    (party_id, member_id, count)
+  select p_party_id, p_member_id, 1
+  where not exists (select 1
+                    from party_approved_member_map
+                    where party_id = p_party_id
+                    and member_id = p_member_id);
+
+  get diagnostics v_count = row_count;
+
+  if v_count = 0 then
+    update party_approved_member_map
+    set count = count + 1
+    where party_id = p_party_id
+      and member_id = p_member_id;
+  end if;
+
+  -- if the relation type is mapped to a relational segment map that too
+
+  select into v_segment_id segment_id
+  from rel_segments s
+  where s.rel_type = p_rel_type
+    and s.group_id = p_party_id;
+
+  if found then
+    insert into party_approved_member_map
+      (party_id, member_id, count)
+    select v_segment_id, p_member_id, 1
+    where not exists (select 1
+                      from party_approved_member_map
+                      where party_id = v_segment_id
+                        and member_id = p_member_id);
+
+    get diagnostics v_count = row_count;
+
+    if v_count = 0 then
+      update party_approved_member_map
+      set count = count + 1
+      where party_id = v_segment_id
+        and member_id = p_member_id;
+    end if;
+
+  end if;
+
+  return 1;
+
+end;' language 'plpgsql';
+
+create or replace function delete_from_party_map(integer, integer, varchar) returns integer as '
+declare
+  p_party_id alias for $1;
+  p_member_id alias for $2;
+  p_rel_type alias for $3;
+  v_segment_id rel_segments.segment_id%TYPE;
+  v_count integer;
+begin
+
+  delete from party_approved_member_map
+  where party_id = p_party_id
+    and member_id = p_member_id
+    and count = 1;
+
+  get diagnostics v_count = row_count;
+
+  if v_count = 0 then
+    update party_approved_member_map
+    set count = count - 1
+    where party_id = p_party_id
+      and member_id = p_member_id;
+  end if;
+
+  -- if the relation type is mapped to a relational segment unmap that too
+
+  select into v_segment_id segment_id
+  from rel_segments s
+  where s.rel_type = p_rel_type
+    and s.group_id = p_party_id;
+
+  if found then
+
+    delete from party_approved_member_map
+    where party_id = v_segment_id
+      and member_id = p_member_id
+      and count = 1;
+
+    get diagnostics v_count = row_count;
+
+    if v_count = 0 then
+      update party_approved_member_map
+      set count = count - 1
+      where party_id = v_segment_id
+        and member_id = p_member_id;
+    end if;
+
+  end if;
+
+  return 1;
+
+end;' language 'plpgsql';
+
+create or replace function group_element_index_in_tr () returns opaque as '
+declare
+  v_member_state membership_rels.member_state%TYPE;
+begin
+
+  select into v_member_state m.member_state
+  from membership_rels m
+  where m.rel_id = new.rel_id;
+
+  -- Only membership_rels are tracked in the party_approved_member_map
+
+  if v_member_state = ''approved'' then
+    perform insert_into_party_map(new.group_id, new.element_id, new.rel_type);
+  end if;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger group_element_index_in_tr before insert on group_element_index
+for each row execute procedure group_element_index_in_tr ();
+
+create or replace function group_element_index_del_tr () returns opaque as '
+begin
+  perform delete_from_party_map(old.group_id, old.element_id, old.rel_type);
+  return old;
+end;' language 'plpgsql';
+
+create trigger group_element_index_del_tr after delete on group_element_index
+for each row execute procedure group_element_index_del_tr (); 
+
+create or replace function membership_rels_in_tr () returns opaque as '
+declare
   v_object_id_one acs_rels.object_id_one%TYPE;
   v_object_id_two acs_rels.object_id_two%TYPE;
   v_rel_type      acs_rels.rel_type%TYPE;
@@ -32,7 +175,7 @@
   from acs_rels
   where rel_id = new.rel_id;
 
-  -- Insert a row for me in the group_member_index.
+  -- Insert a row for me in the group_element_index.
   insert into group_element_index
    (group_id, element_id, rel_id, container_id, 
     rel_type, ancestor_rel_type)
@@ -41,11 +184,11 @@
     v_rel_type, ''membership_rel'');
 
   -- For all groups of which I am a component, insert a
-  -- row in the group_member_index.
+  -- row in the group_element_index.
   for map in select distinct group_id
 	      from group_component_map
 	      where component_id = v_object_id_one 
-  LOOP
+  loop
     insert into group_element_index
      (group_id, element_id, rel_id, container_id,
       rel_type, ancestor_rel_type)
@@ -58,19 +201,63 @@
 
 end;' language 'plpgsql';
 
-create trigger membership_rels_in_tr after insert on membership_rels
-for each row execute procedure membership_rels_in_tr ();
+create or replace function membership_rels_up_tr () returns opaque as '
+declare
+  map             record;
+begin
 
--- show errors
+  if new.member_state = old.member_state then
+    return new;
+  end if;
 
--- a dummy trigger was defined in groups-create.sql
-drop trigger composition_rels_in_tr on composition_rels;
-drop function composition_rels_in_tr();
-create function composition_rels_in_tr () returns opaque as '
+  for map in select group_id, element_id, rel_type
+             from group_element_index
+             where rel_id = new.rel_id
+  loop
+    if new.member_state = ''approved'' then
+      perform insert_into_party_map(map.group_id, map.element_id, map.rel_type);
+    else
+      perform delete_from_party_map(map.group_id, map.element_id, map.rel_type);
+    end if;
+  end loop;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger membership_rels_up_tr before update on membership_rels
+for each row execute procedure membership_rels_up_tr ();
+
+create or replace function membership_rels_del_tr () returns opaque as '
 declare
+  v_error text;
   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;
+  map             record;
+  v_count integer;
+begin
+  -- First check if removing this relation would violate any relational constraints
+  v_error := rel_constraint__violation_if_removed(old.rel_id);
+  if v_error is not null then
+      raise EXCEPTION ''-20000: %'', v_error;
+  end if;
+
+  delete from group_element_index
+  where rel_id = old.rel_id;
+
+  return old;
+
+end;' language 'plpgsql';
+
+create trigger membership_rels_del_tr before delete on membership_rels
+for each row execute procedure membership_rels_del_tr ();
+
+create or replace function composition_rels_in_tr () returns opaque as '
+declare
+  v_object_id_one acs_rels.object_id_one%TYPE;
+  v_object_id_two acs_rels.object_id_two%TYPE;
+  v_rel_type      acs_rels.rel_type%TYPE;
   v_error         text;
   map             record;
 begin
@@ -145,38 +332,11 @@
 
 end;' language 'plpgsql';
 
-create trigger composition_rels_in_tr after insert on composition_rels
-for each row execute procedure composition_rels_in_tr ();
-
--- show errors
-
-create function membership_rels_del_tr () returns opaque as '
-declare
-  v_error text;
-begin
-  -- First check if removing this relation would violate any relational constraints
-  v_error := rel_constraint__violation_if_removed(old.rel_id);
-  if v_error is not null then
-      raise EXCEPTION ''-20000: %'', v_error;
-  end if;
-
-  delete from group_element_index
-  where rel_id = old.rel_id;
-
-  return old;
-
-end;' language 'plpgsql';
-
-create trigger membership_rels_del_tr before delete on membership_rels
-for each row execute procedure membership_rels_del_tr ();
-
--- show errors
-
 --
 -- TO DO: See if this can be optimized now that the member and component
 -- mapping tables have been combined
 --
-create function composition_rels_del_tr () returns opaque as '
+create or replace function composition_rels_del_tr () returns opaque as '
 declare
   v_object_id_one acs_rels.object_id_one%TYPE;
   v_object_id_two acs_rels.object_id_two%TYPE;
@@ -453,12 +613,12 @@
     from acs_rels
     where rel_id = check_representation__rel_id;
 
-    -- First let''s check that the index has all the rows it should.
+    -- First let us check that the index has all the rows it should.
     if composition_rel__check_index(component_id, container_id) = ''f'' then
       result := ''f'';
     end if;
 
-    -- Now let''s check that the index doesn''t have any extraneous rows
+    -- Now let us check that the index doesn''t have any extraneous rows
     -- relating to this relation.
     for row in  select *
                 from group_component_index
@@ -629,15 +789,15 @@
 begin
 
     select count(*) into n_rows
-    from group_member_index
+    from group_element_index
     where group_id = check_index__group_id
     and member_id = check_index__member_id
     and container_id = check_index__container_id;
 
     if n_rows = 0 then
       result := ''f'';
       PERFORM acs_log__error(''membership_rel.check_representation'',
-                    ''Row missing from group_member_index: '' ||
+                    ''Row missing from group_element_index: '' ||
                     ''group_id = '' || check_index__group_id || '', '' ||
                     ''member_id = '' || check_index__member_id || '', '' ||
                     ''container_id = '' || check_index__container_id || ''.'');
Index: openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql,v
diff -u -r1.11 -r1.11.2.1
--- openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql	16 Sep 2002 21:52:42 -0000	1.11
+++ openacs-4/packages/acs-kernel/sql/postgresql/groups-create.sql	11 Feb 2003 17:04:24 -0000	1.11.2.1
@@ -386,7 +386,7 @@
 create function composition_rels_in_tr () returns opaque as '
 declare
 begin
-  raise EXCEPTION ''-20000: Insert to membership rels not yet supported'';
+  raise EXCEPTION ''-20000: Insert to composition rels not yet supported'';
 
   return new;
 
Index: openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql,v
diff -u -r1.3 -r1.3.4.1
--- openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql	1 Dec 2001 17:55:16 -0000	1.3
+++ openacs-4/packages/acs-kernel/sql/postgresql/rel-segments-create.sql	11 Feb 2003 17:04:24 -0000	1.3.4.1
@@ -92,102 +92,10 @@
 
 -- create pl/sql package rel_segment
 
--- create or replace package rel_segment
--- is
---  function new (
---   --/** Creates a new relational segment
---   -- 
---   --    @author Oumi Mehrotra (oumi@arsdigita.com)
---   --    @creation-date 12/2000
---   -- 
---   --*/
---   segment_id            in rel_segments.segment_id%TYPE default null,
---   object_type           in acs_objects.object_type%TYPE
---                            default 'rel_segment',
---   creation_date         in acs_objects.creation_date%TYPE
---                            default sysdate,
---   creation_user         in acs_objects.creation_user%TYPE
---                            default null,
---   creation_ip           in acs_objects.creation_ip%TYPE default null,
---   email                 in parties.email%TYPE default null,
---   url                   in parties.url%TYPE default null,
---   segment_name          in rel_segments.segment_name%TYPE,
---   group_id              in rel_segments.group_id%TYPE,
---   rel_type              in rel_segments.rel_type%TYPE,
---   context_id	in acs_objects.context_id%TYPE default null
---  ) return rel_segments.segment_id%TYPE;
--- 
---  procedure delete (
---     --/** Deletes a relational segment
---     -- 
---     --    @author Oumi Mehrotra (oumi@arsdigita.com)
---     --    @creation-date 12/2000
---     -- 
---     --*/
---    segment_id     in rel_segments.segment_id%TYPE
---  );
--- 
---  function name (
---   segment_id      in rel_segments.segment_id%TYPE
---  ) return rel_segments.segment_name%TYPE;
--- 
---  function get (
---     --/** EXPERIMENTAL / UNSTABLE -- use at your own risk
---     --    Get the id of a segment given a group_id and rel_type.
---     --    This depends on the uniqueness of group_id,rel_type.  We
---     --    might remove the unique constraint in the future, in which
---     --    case we would also probably remove this function.
---     --
---     --    @author Oumi Mehrotra (oumi@arsdigita.com)
---     --    @creation-date 12/2000
---     --
---     --*/
--- 
---    group_id       in rel_segments.group_id%TYPE,
---    rel_type       in rel_segments.rel_type%TYPE
---  ) return rel_segments.segment_id%TYPE;
--- 
---  function get_or_new (
---     --/** EXPERIMENTAL / UNSTABLE -- use at your own risk
---     --
---     --    This function simplifies the use of segments a little by letting
---     --    you not have to worry about creating and initializing segments.
---     --    If the segment you're interested in exists, this function
---     --    returns its segment_id.
---     --    If the segment you're interested in doesn't exist, this function
---     --    does a pretty minimal amount of initialization for the segment
---     --    and returns a new segment_id.
---     --
---     --    @author Oumi Mehrotra (oumi@arsdigita.com)
---     --    @creation-date 12/2000
---     --
---     --*/
---    group_id       in rel_segments.group_id%TYPE,
---    rel_type       in rel_segments.rel_type%TYPE,
---    segment_name   in rel_segments.segment_name%TYPE
---                   default null
---  ) return rel_segments.segment_id%TYPE;
--- 
--- end rel_segment;
-
--- show errors
-
-
 -----------
 -- Views --
 -----------
 
--- create view rel_segment_party_map
--- as select rs.segment_id, gem.element_id as party_id, gem.rel_id, gem.rel_type, 
---           gem.group_id, gem.container_id, gem.ancestor_rel_type
---    from rel_segments rs, 
---         group_element_map gem 
---    where gem.group_id = rs.group_id
---      and rs.rel_type in (select object_type 
---                          from acs_object_types 
---                          start with object_type = gem.rel_type 
---                          connect by prior supertype = object_type);
-
 create view rel_segment_party_map
 as select rs.segment_id, gem.element_id as party_id, gem.rel_id, gem.rel_type, 
           gem.group_id, gem.container_id, gem.ancestor_rel_type
@@ -207,21 +115,6 @@
    from rel_segment_party_map
    where ancestor_rel_type = 'membership_rel';
 
-
--- Need to find out what this optimizer hint does?  DCW, 2001-03-13.
--- create view rel_seg_approved_member_map
--- as select /*+ ordered */ 
---           rs.segment_id, gem.element_id as member_id, gem.rel_id, gem.rel_type, 
---           gem.group_id, gem.container_id
---     from membership_rels mr, group_element_map gem, rel_segments rs
---    where rs.group_id = gem.group_id 
---      and rs.rel_type in (select object_type 
---                          from acs_object_types 
---                          start with object_type = gem.rel_type 
---                          connect by prior supertype = object_type)
---      and mr.rel_id = gem.rel_id and mr.member_state = 'approved';
-
-
 create view rel_seg_approved_member_map
 as select rs.segment_id, gem.element_id as member_id, gem.rel_id, 
           gem.rel_type, gem.group_id, gem.container_id
@@ -237,71 +130,111 @@
 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.  
+-- party_approved_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)
+-- DRB: This is here rather where parties are created for historical reasons
+-- (in other words this is where the old view was created in older versions)
 
-create view party_member_map
-as select segment_id as party_id, member_id
-   from rel_seg_distinct_member_map
-   union
-   select group_id as party_id, member_id
-   from group_distinct_member_map
-   union
-   select party_id, party_id as member_id
-   from parties;
+-- The count column is needed because composition_rels and relational segment
+-- rel_types derived from membership_rel lead to a lot of redundant data in the
+-- group element map (i.e. you can belong to the registered users group an
+-- infinite number of times, strange concept)
 
-create view party_approved_member_map
-as select distinct segment_id as party_id, member_id
-   from rel_seg_approved_member_map
-   union
-   select distinct group_id as party_id, member_id
-   from group_approved_member_map
-   union
-   select party_id, party_id as member_id
-   from parties;
+create table party_approved_member_map (
+    party_id        integer
+                    constraint party_member_party_fk
+                    references parties,
+    member_id       integer
+                    constraint party_member_member_fk
+                    references parties,
+    count           integer,
+    constraint party_member_map_pk
+    primary key (party_id, member_id)
+);
 
--- party_element_map tells us all the parties that "belong to" a party,
--- whether through somet type of membership, composition, or identity.
+-- Need this to speed referential integrity 
+create index party_member_member_idx on party_approved_member_map(member_id);
 
-create view party_element_map
-as select distinct group_id as party_id, element_id
-   from group_element_map
-   union
-   select distinct segment_id as party_id, party_id as element_id
-   from rel_segment_party_map
-   union
-   select party_id, party_id as element_id
-   from parties;
+-- Triggers to maintain party_approved_member_map when parties are created or
+-- destroyed.
 
+create or replace function parties_in_tr () returns opaque as '
+begin
 
+  insert into party_approved_member_map
+    (party_id, member_id, count)
+  values
+    (new.party_id, new.party_id, 1);
+  return new;
+
+
+end;' language 'plpgsql';
+
+create trigger parties_in_tr before insert on parties
+for each row execute procedure parties_in_tr ();
+
+create or replace function parties_del_tr () returns opaque as '
+begin
+
+  delete from party_approved_member_map
+  where party_id = old.party_id
+    and member_id = old.party_id;
+
+  return old;
+
+end;' language 'plpgsql';
+
+create trigger parties_del_tr before delete on parties
+for each row execute procedure parties_del_tr ();
+
+-- Triggers to maintain party_approved_member_map when relational segments are
+-- created or destroyed.   We only remove the (segment_id, member_id) rows as
+-- removing the relational segment itself does not remove members from the
+-- group with that rel_type.  This was intentional on the part of the aD folks
+-- who added relational segments to ACS 4.2.
+
+create or replace function rel_segments_in_tr () returns opaque as '
+begin
+
+  insert into party_approved_member_map
+    (party_id, member_id, count)
+  select new.segment_id, element_id, 1
+    from group_element_index
+    where group_id = new.group_id
+      and rel_type = new.rel_type;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger rel_segments_in_tr before insert on rel_segments
+for each row execute procedure rel_segments_in_tr ();
+
+create or replace function rel_segments_del_tr () returns opaque as '
+begin
+
+  delete from party_approved_member_map
+  where party_id = old.segment_id
+    and member_id in (select element_id
+                      from group_element_index
+                      where group_id = old.group_id
+                        and rel_type = old.rel_type);
+
+  return old;
+
+end;' language 'plpgsql';
+
+create trigger parties_del_tr before delete on rel_segments
+for each row execute procedure rel_segments_del_tr ();
+
 -- View: rel_segment_group_rel_type_map
 --
 -- Result Set: the set of triples (:segment_id, :group_id, :rel_type) such that
 --
 --             IF a party were to be in :group_id 
 --                through a relation of type :rel_type,
 --             THEN the party would necessarily be in segment :segemnt_id.    
---
---
--- create view rel_segment_group_rel_type_map as
--- select s.segment_id, 
---        gcm.component_id as group_id, 
---        acs_rel_types.rel_type as rel_type
--- from rel_segments s,
---      (select group_id, component_id
---       from group_component_map
---       UNION ALL
---       select group_id, group_id as component_id
---       from groups) gcm,
---      acs_rel_types
--- where s.group_id = gcm.group_id
---   and s.rel_type in (select object_type from acs_object_types
---                      start with object_type = acs_rel_types.rel_type
---                      connect by prior supertype = object_type);
  
 create view rel_segment_group_rel_type_map as
 select s.segment_id, 
Index: openacs-4/packages/acs-kernel/sql/postgresql/upgrade/upgrade-4.6-4.6.1.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-kernel/sql/postgresql/upgrade/Attic/upgrade-4.6-4.6.1.sql,v
diff -u -r1.1.2.1 -r1.1.2.2
--- openacs-4/packages/acs-kernel/sql/postgresql/upgrade/upgrade-4.6-4.6.1.sql	17 Dec 2002 10:23:20 -0000	1.1.2.1
+++ openacs-4/packages/acs-kernel/sql/postgresql/upgrade/upgrade-4.6-4.6.1.sql	11 Feb 2003 17:05:21 -0000	1.1.2.2
@@ -23,3 +23,744 @@
     return magic_object_id__object_id;
    
 end;' language 'plpgsql' with(isstrict,iscachable);
+
+-----------------------------------------------------------------------------------------
+
+-- DRB: Change security context to object -4
+
+create or replace function acs_objects_context_id_in_tr () returns opaque as '
+declare
+        security_context_root integer;
+begin
+  insert into acs_object_context_index
+   (object_id, ancestor_id, n_generations)
+  values
+   (new.object_id, new.object_id, 0);
+
+  if new.context_id is not null and new.security_inherit_p = ''t'' then
+    insert into acs_object_context_index
+     (object_id, ancestor_id, n_generations)
+    select
+     new.object_id as object_id, ancestor_id,
+     n_generations + 1 as n_generations
+    from acs_object_context_index
+    where object_id = new.context_id;
+  else
+    security_context_root = acs__magic_object_id(''security_context_root'');
+    if new.object_id != security_context_root then
+      insert into acs_object_context_index
+        (object_id, ancestor_id, n_generations)
+      values
+        (new.object_id, security_context_root, 1);
+    end if;
+  end if;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create or replace function acs_objects_context_id_up_tr () returns opaque as '
+declare
+        pair    record;
+        security_context_root integer;
+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 new;
+  end if;
+
+  -- Remove my old ancestors from my descendants.
+  delete from acs_object_context_index
+  where object_id in (select object_id
+                      from acs_object_contexts
+                      where ancestor_id = old.object_id)
+  and ancestor_id in (select ancestor_id
+		      from acs_object_contexts
+		      where object_id = old.object_id);
+
+  -- Kill all my old ancestors.
+  delete from acs_object_context_index
+  where object_id = old.object_id;
+
+  insert into acs_object_context_index
+   (object_id, ancestor_id, n_generations)
+  values
+   (new.object_id, new.object_id, 0);
+
+  if new.context_id is not null and new.security_inherit_p = ''t'' then
+     -- Now insert my new ancestors for my descendants.
+    for pair in select *
+		 from acs_object_context_index
+		 where ancestor_id = new.object_id 
+    LOOP
+      insert into acs_object_context_index
+       (object_id, ancestor_id, n_generations)
+      select
+       pair.object_id, ancestor_id,
+       n_generations + pair.n_generations + 1 as n_generations
+      from acs_object_context_index
+      where object_id = new.context_id;
+    end loop;
+  else
+    security_context_root = acs__magic_object_id(''security_context_root'');
+    if new.object_id != security_context_root then
+    -- We need to make sure that new.OBJECT_ID and all of its
+    -- children have security_context_root 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, security_context_root, pair.n_generations + 1);
+      end loop;
+    end if;
+  end if;
+
+  return new;
+
+end;' language 'plpgsql';
+
+-- DRB: This is the function that actually changes security_context_root
+-- to -4 rather than 0
+
+drop trigger acs_objects_context_id_in_tr on acs_objects;
+drop trigger acs_objects_context_id_up_tr on acs_objects;
+
+delete from acs_magic_objects
+where name = 'security_context_root';
+
+select acs_object__new (
+  -4,
+  'acs_object',
+  now(),
+  null,
+  null,
+  null
+  );
+
+insert into acs_magic_objects
+ (name, object_id)
+values
+ ('security_context_root', -4);
+
+update acs_object_context_index
+set ancestor_id = -4
+where ancestor_id = 0;
+
+update acs_object_context_index
+set object_id = -4
+where object_id = 0;
+
+update acs_permissions
+set object_id = -4
+where object_id = 0;
+
+-- Content Repository sets parent_id to security_context_root
+-- for content modules
+
+update cr_items
+set parent_id = -4
+where parent_id = 0;
+
+select acs_object__delete(0);
+
+create trigger acs_objects_context_id_in_tr after insert on acs_objects
+for each row execute procedure acs_objects_context_id_in_tr ();
+
+create trigger acs_objects_context_id_up_tr after update on acs_objects
+for each row execute procedure acs_objects_context_id_up_tr ();
+
+-------------------------------------------------------------------------
+
+-- DRB: We now will turn the magic -1 party into a group that contains
+-- all registered users and a new unregistered visitor.  This will allow
+-- us to do all permission checking on a materialized version of the
+-- party_member_map.
+
+-- Make our new "Unregistered Visitor" be object 0, which corresponds
+-- with the user_id assigned throughout the toolkit Tcl code
+
+insert into acs_objects
+  (object_id, object_type)
+values
+  (0, 'person');
+
+insert into parties
+  (party_id)
+values
+  (0);
+
+insert into persons
+  (person_id, first_names, last_name)
+values
+  (0, 'Unregistered', 'Visitor');
+
+insert into acs_magic_objects
+  (name, object_id)
+values
+  ('unregistered_visitor', 0);
+
+-- Now transform the old special -1 party into a legitimate group with
+-- one user, our Unregistered Visitor
+
+update acs_objects
+set object_type = 'group'
+where object_id = -1;
+ 
+insert into groups
+ (group_id, group_name, join_policy)
+values
+ (-1, 'The Public', 'closed');
+
+-- Add our only user, the Unregistered Visitor
+
+select membership_rel__new (
+  null,
+  'membership_rel',
+  acs__magic_object_id('the_public'),      
+  0,
+  'approved',
+  null,
+  null);
+
+-- Now declare "The Public" to be composed of itself and the "Registered
+-- Users" group
+
+select composition_rel__new (
+  null,
+  'composition_rel',
+  acs__magic_object_id('the_public'),
+  acs__magic_object_id('registered_users'),
+  null,
+  null);
+
+-------------------------------------------------------------------------------
+
+-- DRB: Replace the old party_emmber_map and party_approved_member_map views
+-- (they were both the same and very slow) with a table containing the same
+-- information.  This can be used to greatly speed permissions checking.
+
+drop view party_member_map;
+drop view party_approved_member_map;
+
+-- The count column is needed because composition_rels lead to a lot of
+-- redundant data in the group element map (i.e. you can belong to the
+-- registered users group an infinite number of times, strange concept)
+
+-- Though for permission checking we only really need to map parties to
+-- member users, the old view included identity entries for all parties
+-- in the system.  It doesn't cost all that much to maintain the extra
+-- rows so we will, just in case some overly clever programmer out there
+-- depends on it.
+
+create table party_approved_member_map (
+    party_id        integer
+                    constraint party_member_party_fk
+                    references parties,
+    member_id       integer
+                    constraint party_member_member_fk
+                    references parties,
+    count           integer,
+    constraint party_approved_member_map_pk
+    primary key (party_id, member_id)
+);
+
+-- Need this to speed referential integrity 
+create index party_member_member_idx on party_approved_member_map(member_id);
+
+-- Every person is a member of itself
+
+insert into party_approved_member_map
+  (party_id, member_id, count)
+select party_id, party_id, 1
+from parties;
+
+-- Every party is a member if it is an approved member of
+-- some sort of membership_rel
+
+insert into party_approved_member_map
+  (party_id, member_id, count)
+select group_id, member_id, count(*)
+from group_approved_member_map
+group by group_id, member_id;
+
+-- Every party is a member if it is an approved member of
+-- some sort of relation segment
+
+insert into party_approved_member_map
+  (party_id, member_id, count)
+select segment_id, member_id, count(*)
+from rel_seg_approved_member_map
+group by segment_id, member_id;
+
+analyze party_approved_member_map;
+
+-- Triggers to maintain party_approved_member_map when parties are created or
+-- destroyed.
+
+create or replace function parties_in_tr () returns opaque as '
+begin
+
+  insert into party_approved_member_map
+    (party_id, member_id, count)
+  values
+    (new.party_id, new.party_id, 1);
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger parties_in_tr before insert on parties
+for each row execute procedure parties_in_tr ();
+
+create or replace function parties_del_tr () returns opaque as '
+begin
+
+  delete from party_approved_member_map
+  where party_id = old.party_id
+    and member_id = old.party_id;
+
+  return old;
+
+end;' language 'plpgsql';
+
+create trigger parties_del_tr before delete on parties
+for each row execute procedure parties_del_tr ();
+
+-- Triggers to maintain party_approved_member_map when relational segments are
+-- created or destroyed.   We only remove the (segment_id, member_id) rows as
+-- removing the relational segment itself does not remove members from the
+-- group with that rel_type.  This was intentional on the part of the aD folks
+-- who added relational segments to ACS 4.2.
+
+create or replace function rel_segments_in_tr () returns opaque as '
+begin
+
+  insert into party_approved_member_map
+    (party_id, member_id, count)
+  select new.segment_id, element_id, 1
+    from group_element_index
+    where group_id = new.group_id
+      and rel_type = new.rel_type;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger rel_segments_in_tr before insert on rel_segments
+for each row execute procedure rel_segments_in_tr ();
+
+create or replace function rel_segments_del_tr () returns opaque as '
+begin
+
+  delete from party_approved_member_map
+  where party_id = old.segment_id
+    and member_id in (select element_id
+                      from group_element_index
+                      where group_id = old.group_id
+                        and rel_type = old.rel_type);
+
+  return old;
+
+end;' language 'plpgsql';
+
+create trigger parties_del_tr before delete on rel_segments
+for each row execute procedure rel_segments_del_tr ();
+
+
+-- DRB: Helper functions to maintain the materialized party_approved_member_map.  The counting crap
+-- has to do with the way composition_rels work, which is not how any sane person would care
+-- for them to work.   Fixing the groups and relational segments model will be a nice future project.
+-- For now I will just settle for making permission checking fast ...
+
+create or replace function insert_into_party_map(integer, integer, varchar) returns integer as '
+declare
+  p_party_id alias for $1;
+  p_member_id alias for $2;
+  p_rel_type alias for $3;
+  v_segment_id rel_segments.segment_id%TYPE;
+  v_count integer;
+begin
+
+  insert into party_approved_member_map
+    (party_id, member_id, count)
+  select p_party_id, p_member_id, 1
+  where not exists (select 1
+                    from party_approved_member_map
+                    where party_id = p_party_id
+                    and member_id = p_member_id);
+
+  get diagnostics v_count = row_count;
+
+  if v_count = 0 then
+    update party_approved_member_map
+    set count = count + 1
+    where party_id = p_party_id
+      and member_id = p_member_id;
+  end if;
+
+  -- if the relation type is mapped to a relational segment map that too
+
+  select into v_segment_id segment_id
+  from rel_segments s
+  where s.rel_type = p_rel_type
+    and s.group_id = p_party_id;
+
+  if found then
+    insert into party_approved_member_map
+      (party_id, member_id, count)
+    select v_segment_id, p_member_id, 1
+    where not exists (select 1
+                      from party_approved_member_map
+                      where party_id = v_segment_id
+                        and member_id = p_member_id);
+
+    get diagnostics v_count = row_count;
+
+    if v_count = 0 then
+      update party_approved_member_map
+      set count = count + 1
+      where party_id = v_segment_id
+        and member_id = p_member_id;
+    end if;
+
+  end if;
+
+  return 1;
+
+end;' language 'plpgsql';
+
+create or replace function delete_from_party_map(integer, integer, varchar) returns integer as '
+declare
+  p_party_id alias for $1;
+  p_member_id alias for $2;
+  p_rel_type alias for $3;
+  v_segment_id rel_segments.segment_id%TYPE;
+  v_count integer;
+begin
+
+  delete from party_approved_member_map
+  where party_id = p_party_id
+    and member_id = p_member_id
+    and count = 1;
+
+  get diagnostics v_count = row_count;
+
+  if v_count = 0 then
+    update party_approved_member_map
+    set count = count - 1
+    where party_id = p_party_id
+      and member_id = p_member_id;
+  end if;
+
+  -- if the relation type is mapped to a relational segment unmap that too
+
+  select into v_segment_id segment_id
+  from rel_segments s
+  where s.rel_type = p_rel_type
+    and s.group_id = p_party_id;
+
+  if found then
+
+    delete from party_approved_member_map
+    where party_id = v_segment_id
+      and member_id = p_member_id
+      and count = 1;
+
+    get diagnostics v_count = row_count;
+
+    if v_count = 0 then
+      update party_approved_member_map
+      set count = count - 1
+      where party_id = v_segment_id
+        and member_id = p_member_id;
+    end if;
+
+  end if;
+
+  return 1;
+
+end;' language 'plpgsql';
+
+create or replace function group_element_index_in_tr () returns opaque as '
+declare
+  v_member_state membership_rels.member_state%TYPE;
+begin
+
+  select into v_member_state m.member_state
+  from membership_rels m
+  where m.rel_id = new.rel_id;
+
+  -- Only membership_rels are tracked in the party_approved_member_map
+
+  if v_member_state = ''approved'' then
+    perform insert_into_party_map(new.group_id, new.element_id, new.rel_type);
+  end if;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger group_element_index_in_tr before insert on group_element_index
+for each row execute procedure group_element_index_in_tr ();
+
+create or replace function group_element_index_del_tr () returns opaque as '
+begin
+  perform delete_from_party_map(old.group_id, old.element_id, old.rel_type);
+  return old;
+end;' language 'plpgsql';
+
+create trigger group_element_index_del_tr after delete on group_element_index
+for each row execute procedure group_element_index_del_tr (); 
+
+create or replace function membership_rels_in_tr () returns opaque as '
+declare
+  v_object_id_one acs_rels.object_id_one%TYPE;
+  v_object_id_two acs_rels.object_id_two%TYPE;
+  v_rel_type      acs_rels.rel_type%TYPE;
+  v_error         text;
+  map             record;
+begin
+  
+  -- First check if added this relation violated any relational constraints
+  v_error := rel_constraint__violation(new.rel_id);
+  if v_error is not null then
+      raise EXCEPTION ''-20000: %'', v_error;
+  end if;
+
+  select object_id_one, object_id_two, rel_type
+  into v_object_id_one, v_object_id_two, v_rel_type
+  from acs_rels
+  where rel_id = new.rel_id;
+
+  -- Insert a row for me in the group_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, ''membership_rel'');
+
+  -- For all groups of which I am a component, insert a
+  -- row in the group_element_index.
+  for map in select distinct group_id
+	      from group_component_map
+	      where component_id = v_object_id_one 
+  loop
+    insert into group_element_index
+     (group_id, element_id, rel_id, container_id,
+      rel_type, ancestor_rel_type)
+    values
+     (map.group_id, v_object_id_two, new.rel_id, v_object_id_one,
+      v_rel_type, ''membership_rel'');
+  end loop;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create or replace function membership_rels_up_tr () returns opaque as '
+declare
+  map             record;
+begin
+
+  if new.member_state = old.member_state then
+    return new;
+  end if;
+
+  for map in select group_id, element_id, rel_type
+             from group_element_index
+             where rel_id = new.rel_id
+  loop
+    if new.member_state = ''approved'' then
+      perform insert_into_party_map(map.group_id, map.element_id, map.rel_type);
+    else
+      perform delete_from_party_map(map.group_id, map.element_id, map.rel_type);
+    end if;
+  end loop;
+
+  return new;
+
+end;' language 'plpgsql';
+
+create trigger membership_rels_up_tr before update on membership_rels
+for each row execute procedure membership_rels_up_tr ();
+
+create or replace function membership_rels_del_tr () returns opaque as '
+declare
+  v_error text;
+  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;
+  map             record;
+  v_count integer;
+begin
+  -- First check if removing this relation would violate any relational constraints
+  v_error := rel_constraint__violation_if_removed(old.rel_id);
+  if v_error is not null then
+      raise EXCEPTION ''-20000: %'', v_error;
+  end if;
+
+  delete from group_element_index
+  where rel_id = old.rel_id;
+
+  return old;
+
+end;' language 'plpgsql';
+
+------------------------------------------------------------------------------------
+
+-- DRB: upgrade to Dan Wickstrom's version of acs-permissions which materializes the
+-- acs_privilege_descendant_map view.
+
+drop view acs_privilege_descendant_map;
+create table acs_privilege_descendant_map (
+	privilege       varchar(100) not null 
+                        constraint acs_priv_hier_priv_fk
+			references acs_privileges (privilege),
+        descendant      varchar(100) not null 
+                        constraint acs_priv_hier_child_priv_fk
+			references acs_privileges (privilege)
+
+);
+
+-- DRB: Empirical testing showed that even with just 61 entries in the new table
+-- this index sped things up by roughly 15%
+
+create index acs_priv_desc_map_idx on acs_privilege_descendant_map(descendant);
+
+insert into acs_privilege_descendant_map
+select privilege, descendant from acs_privilege_descendant_map_view;
+
+drop view acs_object_grantee_priv_map;
+create view acs_object_grantee_priv_map as
+select a.object_id, a.grantee_id, m.descendant as privilege
+   from acs_permissions_all a, acs_privilege_descendant_map m
+   where a.privilege = m.privilege;
+
+create or replace function acs_priv_hier_ins_del_tr () returns opaque as '
+declare
+        new_value       integer;
+        new_key         varbit default null;
+        v_rec           record;
+        deleted_p       boolean;
+begin
+        -- if more than one node was deleted the second trigger call
+        -- will error out.  This check avoids that problem.
+
+        if TG_OP = ''DELETE'' then 
+            select count(*) = 0 into deleted_p
+              from acs_privilege_hierarchy_index 
+             where old.privilege = privilege
+               and old.child_privilege = child_privilege;     
+       
+            if deleted_p then
+
+                return new;
+
+            end if;
+        end if;
+
+        -- recalculate the table from scratch.
+
+        delete from acs_privilege_hierarchy_index;
+
+        -- first find the top nodes of the tree
+
+        for v_rec in select privilege, child_privilege
+                       from acs_privilege_hierarchy
+                      where privilege 
+                            NOT in (select distinct child_privilege
+                                      from acs_privilege_hierarchy)
+                                           
+        LOOP
+
+            -- top level node, so find the next key at this level.
+
+            select max(tree_leaf_key_to_int(tree_sortkey)) into new_value 
+              from acs_privilege_hierarchy_index
+             where tree_level(tree_sortkey) = 1;
+
+             -- insert the new node
+
+            insert into acs_privilege_hierarchy_index 
+                        (privilege, child_privilege, tree_sortkey)
+                        values
+                        (v_rec.privilege, v_rec.child_privilege, tree_next_key(null, new_value));
+
+            -- now recurse down from this node
+
+            PERFORM priv_recurse_subtree(tree_next_key(null, new_value), v_rec.child_privilege);
+
+        end LOOP;
+
+        -- materialize the map view to speed up queries
+        -- DanW (dcwickstrom@earthlink.net) 30 Jan, 2003
+        delete from acs_privilege_descendant_map;
+
+        insert into acs_privilege_descendant_map (privilege, descendant) 
+        select privilege, descendant from acs_privilege_descendant_map_view;
+
+        return new;
+
+end;' language 'plpgsql';
+
+create view acs_privilege_descendant_map_view
+as select p1.privilege, p2.privilege as descendant
+   from acs_privileges p1, acs_privileges p2
+   where exists (select h2.child_privilege
+                   from
+                     acs_privilege_hierarchy_index h1,
+                     acs_privilege_hierarchy_index h2
+                   where
+                     h1.privilege = p1.privilege
+                     and h2.privilege = p2.privilege
+                     and h2.tree_sortkey between h1.tree_sortkey and tree_right(h1.tree_sortkey)) or
+     p1.privilege = p2.privilege;
+
+insert into acs_privilege_descendant_map (privilege, descendant) 
+select privilege, descendant from acs_privilege_descendant_map_view;
+
+-- New fast version of acs_object_party_privilege_map
+
+drop view acs_object_party_privilege_map;
+create view acs_object_party_privilege_map as
+select c.object_id, pdm.descendant as privilege, pamm.member_id as party_id
+from acs_object_context_index c, acs_permissions p, acs_privilege_descendant_map pdm,
+  party_approved_member_map pamm
+where c.ancestor_id = p.object_id
+  and pdm.privilege = p.privilege
+  and pamm.party_id = p.grantee_id;
+
+drop view all_object_party_privilege_map;
+create view all_object_party_privilege_map as
+select * from acs_object_party_privilege_map;
+
+-- Really speedy version of permission_p written by Don Baccus
+
+create or replace function acs_permission__permission_p (integer,integer,varchar)
+returns boolean as '
+declare
+    permission_p__object_id           alias for $1;
+    permission_p__party_id            alias for $2;
+    permission_p__privilege           alias for $3;
+    exists_p                          boolean;
+begin
+  return exists (select 1
+                 from acs_permissions p, party_approved_member_map m,
+                   acs_object_context_index c, acs_privilege_descendant_map h
+                 where p.object_id = c.ancestor_id
+                   and h.descendant = permission_p__privilege
+                   and c.object_id = permission_p__object_id
+                   and m.member_id = permission_p__party_id
+                   and p.privilege = h.privilege
+                   and p.grantee_id = m.party_id);
+end;' language 'plpgsql';
+
+-- No longer needed with fast acs_object_party_privilege_map
+drop function acs_permission__user_with_perm_exists_p (integer,varchar);
+
+
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.3 -r1.3.4.1
--- openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.tcl	21 Mar 2001 00:26:19 -0000	1.3
+++ openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.tcl	11 Feb 2003 17:06:36 -0000	1.3.4.1
@@ -10,15 +10,7 @@
     @return 1 if a user with admin privileges exists, 0 otherwise.
 
 } {
-    return [db_string admin_exists_p {
-	select 1 as admin_exists_p
-	from dual
-	where exists (select 1
-		      from acs_object_party_privilege_map m, users u
-		      where m.object_id = 0
-		      and m.party_id = u.user_id
-		      and m.privilege = 'admin')
-    } -default 0]
+    return [db_string admin_exists_p {} -default 0]
 }
 
 
Index: openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/Attic/acs-kernel-procs.xql,v
diff -u -r1.2 -r1.2.4.1
--- openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.xql	28 Nov 2001 18:39:39 -0000	1.2
+++ openacs-4/packages/acs-tcl/tcl/acs-kernel-procs.xql	11 Feb 2003 17:06:36 -0000	1.2.4.1
@@ -7,10 +7,11 @@
 	select 1 as admin_exists_p
 	from dual
 	where exists (select 1
-		      from all_object_party_privilege_map m, users u
-		      where m.object_id = 0
-		      and m.party_id = u.user_id
-		      and m.privilege = 'admin')
+		      from all_object_party_privilege_map m, users u, acs_magic_objects amo
+		      where m.object_id = amo.object_id
+                        and amo.name = 'security_context_root'
+		        and m.party_id = u.user_id
+		        and m.privilege = 'admin')
     
       </querytext>
 </fullquery>
Index: openacs-4/packages/cms/sql/postgresql/cms-content-methods.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-content-methods.sql,v
diff -u -r1.4 -r1.4.4.1
--- openacs-4/packages/cms/sql/postgresql/cms-content-methods.sql	8 Jun 2001 01:44:53 -0000	1.4
+++ openacs-4/packages/cms/sql/postgresql/cms-content-methods.sql	11 Feb 2003 17:07:33 -0000	1.4.4.1
@@ -125,7 +125,7 @@
 
 -- create or replace package body content_method as
 -- function get_method
-create function content_method__get_method (varchar)
+create or replace function content_method__get_method (varchar)
 returns varchar as '
 declare
   p_content_type                alias for $1;  
@@ -173,7 +173,7 @@
 
 
 -- function is_mapped
-create function content_method__is_mapped (varchar,varchar)
+create or replace function content_method__is_mapped (varchar,varchar)
 returns boolean as '
 declare
   p_content_type          alias for $1;  
@@ -193,7 +193,7 @@
 
 
 -- procedure add_method
-create function content_method__add_method (varchar,varchar,boolean)
+create or replace function content_method__add_method (varchar,varchar,boolean)
 returns integer as '
 declare
   p_content_type                alias for $1;  
@@ -234,7 +234,7 @@
 
 
 -- procedure add_all_methods
-create function content_method__add_all_methods (varchar)
+create or replace function content_method__add_all_methods (varchar)
 returns integer as '
 declare
   p_content_type    alias for $1;  
@@ -262,7 +262,7 @@
 
 
 -- procedure set_default_method
-create function content_method__set_default_method (varchar,varchar)
+create or replace function content_method__set_default_method (varchar,varchar)
 returns integer as '
 declare
   p_content_type      alias for $1;  
@@ -284,7 +284,7 @@
 
 
 -- procedure unset_default_method
-create function content_method__unset_default_method (varchar)
+create or replace function content_method__unset_default_method (varchar)
 returns integer as '
 declare
   p_content_type   alias for $1;  
@@ -299,7 +299,7 @@
 
 
 -- procedure remove_method
-create function content_method__remove_method (varchar,varchar)
+create or replace function content_method__remove_method (varchar,varchar)
 returns integer as '
 declare
   p_content_type      alias for $1;  
Index: openacs-4/packages/cms/sql/postgresql/cms-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-create.sql,v
diff -u -r1.5.4.2 -r1.5.4.3
--- openacs-4/packages/cms/sql/postgresql/cms-create.sql	31 Jan 2003 20:26:13 -0000	1.5.4.2
+++ openacs-4/packages/cms/sql/postgresql/cms-create.sql	11 Feb 2003 17:07:33 -0000	1.5.4.3
@@ -14,7 +14,7 @@
 
 \i cms-update.sql
 
-create function inline_0 ()
+create or replace function inline_0 ()
 returns integer as '
 declare
  attr_id	acs_attributes.attribute_id%TYPE;
@@ -149,7 +149,7 @@
 
 -- create or replace package body content_module
 
-create function content_module__new (varchar,varchar,varchar,integer,integer)
+create or replace function content_module__new (varchar,varchar,varchar,integer,integer)
 returns integer as '
 declare
   p_name                        alias for $1;  
@@ -172,14 +172,14 @@
                                    );
 end;' language 'plpgsql';
 
-create function content_module__new (varchar,varchar,integer,integer,integer)
+create or replace function content_module__new (varchar,varchar,integer,integer,integer)
 returns integer as '
 begin
     return content_module__new ($1, $2, cast ($3 as varchar), $4, $5);
 end;' language 'plpgsql';
 
 -- function new
-create function content_module__new (varchar,varchar,varchar,integer,integer,integer,timestamp with time zone,integer,varchar,varchar)
+create or replace function content_module__new (varchar,varchar,varchar,integer,integer,integer,timestamp with time zone,integer,varchar,varchar)
 returns integer as '
 declare
   p_name                        alias for $1;  
@@ -223,7 +223,7 @@
 end;' language 'plpgsql';
 
 
-create function content_module__get_label (integer) returns varchar as '
+create or replace function content_module__get_label (integer) returns varchar as '
 declare
         p_module_id     alias for $1;
         v_name          cm_modules.name%TYPE;
@@ -241,7 +241,7 @@
 end;' language 'plpgsql';
 
 -- Insert the default modules
-create function inline_1 () returns integer as '
+create or replace function inline_1 () returns integer as '
 declare 
   v_id		integer;
   v_module_id	integer;
@@ -271,7 +271,7 @@
 
 -- Get the alphabetical ordering of a string, based on the first
 -- character. Treat all non-alphabetical characters as before ''a''
-create function letter_placement (varchar) returns integer as '
+create or replace function letter_placement (varchar) returns integer as '
 declare
   p_word          alias for $1;
   v_letter        varchar(1);
Index: openacs-4/packages/cms/sql/postgresql/cms-fix.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-fix.sql,v
diff -u -r1.4 -r1.4.4.1
--- openacs-4/packages/cms/sql/postgresql/cms-fix.sql	22 May 2001 22:46:13 -0000	1.4
+++ openacs-4/packages/cms/sql/postgresql/cms-fix.sql	11 Feb 2003 17:07:33 -0000	1.4.4.1
@@ -13,7 +13,7 @@
 -- content_module inherit from content_item
 -- this way it is possible to grant permissions on content modules
 
-create function inline_0 ()
+create or replace function inline_0 ()
 returns integer as '
 declare
   v_user_id             users.user_id%TYPE;
Index: openacs-4/packages/cms/sql/postgresql/cms-forms.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-forms.sql,v
diff -u -r1.4.4.2 -r1.4.4.3
--- openacs-4/packages/cms/sql/postgresql/cms-forms.sql	6 Feb 2003 15:56:31 -0000	1.4.4.2
+++ openacs-4/packages/cms/sql/postgresql/cms-forms.sql	11 Feb 2003 17:07:33 -0000	1.4.4.3
@@ -120,99 +120,8 @@
   order by
     object_type, sort_order;
 
--- create or replace package cm_form_widget 
--- is
--- 
--- procedure set_attribute_order (
---   --/** Update the sort_order column of acs_attributes.
---   --    @author Karl Goldstein
---   --    @param content_type   The name of the content type
---   --    @param attribute_name The name of the attribute
---   --    @param sort_order     The sort order.
---   --*/
---   content_type   in acs_attributes.object_type%TYPE,
---   attribute_name in acs_attributes.attribute_name%TYPE,
---   sort_order     in acs_attributes.sort_order%TYPE
--- );
--- 
--- procedure register_attribute_widget (
---   --/** Register a form widget to a content type attribute.  The form widget
---   --    uses the default values if none are set. If there is already a widget
---   --    registered to the attribute, the new widget replaces the old widget,
---   --    and all parameters are set to their default values.
---   --    @author Karl Goldstein, Stanislav Freidin
---   --    @param content_type   The name of the content type
---   --    @param attribute_name The name of the attribute
---   --	@param widget	      The name of the form widget to use in metadata
---   --			      forms
---   --	@param is_required    Whether this form widget requires a value, 
---   --			      defaults to 'f'
---   --    @see <a href="">/ats/form-procs.tcl/element_create</a>,
---   --         {cm_form_widget.set_attribute_param_value},
---   --         {cm_form_widget.unregister_attribute_widget}
---   --*/
---   content_type   in acs_attributes.object_type%TYPE,
---   attribute_name in acs_attributes.attribute_name%TYPE,
---   widget         in cm_form_widgets.widget%TYPE,
---   is_required    in cm_attribute_widgets.is_required%TYPE default 'f'
--- );
--- 
--- procedure unregister_attribute_widget (
---   --/** Unregister a form widget from a content type attribute. 
---   --    The attribute will no longer show up on the dynamic revision
---   --    upload form.<p>If no widget is registered to the attribute,
---   --    the procedure does nothing.
---   --    @author Karl Goldstein, Stanislav Freidin 
---   --    @param content_type   The name of the content type
---   --    @param attribute_name The name of the attribute for which to
---   --                          unregister the widget
---   --    @see {cm_form_widget.register_attribute_widget}
---   --*/
---   content_type   in acs_attributes.object_type%TYPE,
---   attribute_name in acs_attributes.attribute_name%TYPE
--- );
--- 
--- procedure set_attribute_param_value (
---   --/** Sets custom values for the param tag of a form widget that is 
---   --    registered to a content type attribute. Unless this procedure is
---   --    called, the default form widget param values are used.<p>
---   --    If the parameter already has a value associated with it, the old
---   --    value is overwritten.
---   --    @author Karl Goldstein, Stanislav Freidin
---   --    @param content_type   The name of the content type
---   --    @param attribute_name The name of the attribute
---   --    @param param	      The name of the form widget parameter.
---   --			      Can be an ATS 'element create' flag or an
---   --			      HTML form widget tag
---   --    @param param_type     The type of value the param tag expects.
---   --			      Can be 'onevalue','onelist', or 'multilist',
---   --			      defaults to 'onevalue'
---   --    @param param_source   How the param value is to be acquired, either
---   --			      'literal', 'eval', or 'query', defaults to
---   --			      'literal'
---   --    @param value	      The value(s) or means or obtaining the value(s)
---   --			      for the param tag
---   --    @see <a href="">/ats/form-procs.tcl/element_create</a>,
---   --         {cm_form_widget.register_attribute_widget}
---   --*/
---   content_type   in acs_attributes.object_type%TYPE,
---   attribute_name in acs_attributes.attribute_name%TYPE,
---   param          in cm_form_widget_params.param%TYPE,
---   value          in cm_attribute_widget_params.value%TYPE,
---   param_type     in cm_attribute_widget_params.param_type%TYPE 
---                     default 'onevalue',
---   param_source   in cm_attribute_widget_params.param_source%TYPE
---                     default 'literal'
--- );
--- 
--- end cm_form_widget;
 
--- show errors
-
-
--- create or replace package body cm_form_widget 
--- procedure register_attribute_widget
-create function cm_form_widget__register_attribute_widget (varchar,varchar,varchar,boolean)
+create or replace function cm_form_widget__register_attribute_widget (varchar,varchar,varchar,boolean)
 returns integer as '
 declare
   p_content_type        alias for $1;  
@@ -272,7 +181,7 @@
 
 
 -- procedure set_attribute_order
-create function cm_form_widget__set_attribute_order (varchar,varchar,integer)
+create or replace function cm_form_widget__set_attribute_order (varchar,varchar,integer)
 returns integer as '
 declare
   p_content_type        alias for $1;  
@@ -295,7 +204,7 @@
 
 
 -- procedure unregister_attribute_widget
-create function cm_form_widget__unregister_attribute_widget (varchar,varchar)
+create or replace function cm_form_widget__unregister_attribute_widget (varchar,varchar)
 returns integer as '
 declare
   p_content_type        alias for $1;  
@@ -337,7 +246,7 @@
 
 
 -- procedure set_attribute_param_value
-create function cm_form_widget__set_attribute_param_value (varchar,varchar,varchar,varchar,varchar,varchar)
+create or replace function cm_form_widget__set_attribute_param_value (varchar,varchar,varchar,varchar,varchar,varchar)
 returns integer as '
 declare
   p_content_type        alias for $1;  
@@ -405,13 +314,10 @@
     return 0; 
 end;' language 'plpgsql';
 
-create function cm_form_widget__set_attribute_param_value (varchar,varchar,varchar,integer,varchar,varchar)
+create or replace function cm_form_widget__set_attribute_param_value (varchar,varchar,varchar,integer,varchar,varchar)
 returns integer as '
 begin
     return cm_form_widget__set_attribute_param_value($1, $2, $3, cast ($4 as varchar), $5, $6); 
 end;' language 'plpgsql';
 
--- show errors
-
-
 \i cms-widgets.sql
Index: openacs-4/packages/cms/sql/postgresql/cms-permissions.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-permissions.sql,v
diff -u -r1.9 -r1.9.2.1
--- openacs-4/packages/cms/sql/postgresql/cms-permissions.sql	20 Sep 2002 03:54:26 -0000	1.9
+++ openacs-4/packages/cms/sql/postgresql/cms-permissions.sql	11 Feb 2003 17:07:33 -0000	1.9.2.1
@@ -1,7 +1,7 @@
 -- This file will eventually replace content-perms.sql
 -- Implements the CMS permission
 
-create function inline_0 ()
+create or replace function inline_0 ()
 returns integer as '
 declare
   v_perms       boolean default ''f'';
@@ -220,7 +220,7 @@
 
 -- create or replace package body cms_permission
 -- procedure update_permissions
-create function cms_permission__update_permissions (integer,varchar)
+create or replace function cms_permission__update_permissions (integer,varchar)
 returns integer as '
 declare
   p_item_id                        alias for $1;  
@@ -311,7 +311,7 @@
 
 
 -- function has_grant_authority
-create function cms_permission__has_grant_authority (integer,integer,varchar)
+create or replace function cms_permission__has_grant_authority (integer,integer,varchar)
 returns boolean as '
 declare
   p_item_id                        alias for $1;  
@@ -335,7 +335,7 @@
 
 
 -- function has_revoke_authority
-create function cms_permission__has_revoke_authority (integer,integer,varchar,integer)
+create or replace function cms_permission__has_revoke_authority (integer,integer,varchar,integer)
 returns boolean as '
 declare
   p_item_id                        alias for $1;  
@@ -371,7 +371,7 @@
 );
 insert into v_items (value) values ('{0}');
 
-create function v_items_tr () returns opaque as '
+create or replace function v_items_tr () returns opaque as '
 begin
         raise EXCEPTION ''Only updates are allowed on this table'';
         return null;
@@ -386,7 +386,7 @@
 );
 insert into v_perms (value) values ('{''}');
 
-create function v_perms_tr () returns opaque as '
+create or replace function v_perms_tr () returns opaque as '
 begin
         raise EXCEPTION ''Only updates are allowed on this table'';
         return null;
@@ -398,7 +398,7 @@
 -- procedure grant_permission
 -- FIXME: need to fix problem with defined types
 
-create function cms_permission__grant_permission (integer,integer,varchar,integer,varchar)
+create or replace function cms_permission__grant_permission (integer,integer,varchar,integer,varchar)
 returns integer as '
 declare
   p_item_id                        alias for $1;  
@@ -487,7 +487,7 @@
 
 
 -- procedure revoke_permission
-create function cms_permission__revoke_permission (integer,integer,varchar,integer,varchar)
+create or replace function cms_permission__revoke_permission (integer,integer,varchar,integer,varchar)
 returns integer as '
 declare
   p_item_id                        alias for $1;  
@@ -583,7 +583,7 @@
 
 
 -- function permission_p
-create function cms_permission__permission_p (integer,integer,varchar)
+create or replace function cms_permission__permission_p (integer,integer,varchar)
 returns boolean as '
 declare
   p_item_id                        alias for $1;  
@@ -667,7 +667,7 @@
     
 end;' language 'plpgsql';
 
-create function cms_permission__cm_admin_exists() returns boolean as '
+create or replace function cms_permission__cm_admin_exists() returns boolean as '
 declare
     v_exists    boolean;
 begin
@@ -692,7 +692,7 @@
 -- A trigger to automatically grant item creators the cm_write and cm_perm
 -- permissions
 
-create function cr_items_permission_tr () returns opaque as '
+create or replace function cr_items_permission_tr () returns opaque as '
 declare
   v_user_id parties.party_id%TYPE;
 begin
@@ -808,7 +808,7 @@
 
 -- create or replace package body content_permission 
 -- procedure inherit_permissions
-create function content_permission__inherit_permissions (integer,integer,integer)
+create or replace function content_permission__inherit_permissions (integer,integer,integer)
 returns integer as '
 declare
   p_parent_object_id               alias for $1;  
@@ -821,7 +821,7 @@
 
 
 -- function has_grant_authority
-create function content_permission__has_grant_authority (integer,integer,varchar)
+create or replace function content_permission__has_grant_authority (integer,integer,varchar)
 returns boolean as '
 declare
   p_object_id                      alias for $1;  
@@ -836,7 +836,7 @@
 
 
 -- procedure grant_permission_h
-create function content_permission__grant_permission_h (integer,integer,varchar)
+create or replace function content_permission__grant_permission_h (integer,integer,varchar)
 returns integer as '
 declare
   p_object_id                      alias for $1;  
@@ -848,7 +848,7 @@
 
 
 -- procedure grant_permission
-create function content_permission__grant_permission (integer,integer,varchar,integer,varchar,varchar)
+create or replace function content_permission__grant_permission (integer,integer,varchar,integer,varchar,varchar)
 returns integer as '
 declare
   p_object_id                      alias for $1;  
@@ -867,7 +867,7 @@
 
 
 -- function has_revoke_authority
-create function content_permission__has_revoke_authority (integer,integer,varchar,integer)
+create or replace function content_permission__has_revoke_authority (integer,integer,varchar,integer)
 returns boolean as '
 declare
   p_object_id                      alias for $1;  
@@ -883,7 +883,7 @@
 
 
 -- procedure revoke_permission_h
-create function content_permission__revoke_permission_h (integer,integer,varchar)
+create or replace function content_permission__revoke_permission_h (integer,integer,varchar)
 returns integer as '
 declare
   p_object_id                      alias for $1;  
@@ -895,7 +895,7 @@
 
 
 -- procedure revoke_permission
-create function content_permission__revoke_permission (integer,integer,varchar,integer,varchar,varchar)
+create or replace function content_permission__revoke_permission (integer,integer,varchar,integer,varchar,varchar)
 returns integer as '
 declare
   p_object_id                      alias for $1;  
@@ -914,7 +914,7 @@
 
 
 -- function permission_p
-create function content_permission__permission_p (integer,integer,varchar)
+create or replace function content_permission__permission_p (integer,integer,varchar)
 returns boolean as '
 declare
   p_object_id                      alias for $1;  
Index: openacs-4/packages/cms/sql/postgresql/cms-publishing-wf.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-publishing-wf.sql,v
diff -u -r1.8.2.1 -r1.8.2.2
--- openacs-4/packages/cms/sql/postgresql/cms-publishing-wf.sql	8 Oct 2002 17:03:20 -0000	1.8.2.1
+++ openacs-4/packages/cms/sql/postgresql/cms-publishing-wf.sql	11 Feb 2003 17:07:33 -0000	1.8.2.2
@@ -6,7 +6,7 @@
                  references wf_cases
 );
 
-create function inline_0 ()
+create or replace function inline_0 ()
 returns integer as '
 declare
   v_workflow_key varchar(100);
@@ -244,7 +244,7 @@
 
 -- create or replace package body publishing_wf as
 -- function is_next
-create function publishing_wf__is_next (integer,varchar,varchar,varchar,varchar,varchar)
+create or replace function publishing_wf__is_next (integer,varchar,varchar,varchar,varchar,varchar)
 returns char as '
 declare
   p_case_id                        alias for $1;  
@@ -268,7 +268,7 @@
 end;' language 'plpgsql';
 
 
-create function inline_2 ()
+create or replace function inline_2 ()
 returns integer as '
 declare
     v_attribute_id acs_attributes.attribute_id%TYPE;
Index: openacs-4/packages/cms/sql/postgresql/cms-update.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-update.sql,v
diff -u -r1.3 -r1.3.4.1
--- openacs-4/packages/cms/sql/postgresql/cms-update.sql	22 May 2001 22:46:13 -0000	1.3
+++ openacs-4/packages/cms/sql/postgresql/cms-update.sql	11 Feb 2003 17:07:33 -0000	1.3.4.1
@@ -1,6 +1,6 @@
 
 -- Modify permissions to include the cm_relate permission
-create function inline_0 ()
+create or replace function inline_0 ()
 returns integer as '
 declare
   v_exists integer;
@@ -33,7 +33,7 @@
 -- This parent_id column was not included in the cr_keywords table
 -- for RC 0.  Ensure this column is there.
 
-create function inline_1 ()
+create or replace function inline_1 ()
 returns integer as '
 begin
 
@@ -63,7 +63,7 @@
 -- show errors
 
 -- Drop the broken trigger, if any
-create function inline_2 ()
+create or replace function inline_2 ()
 returns integer as '
 begin
   -- FIXME: DCW - can''t locate where this trigger is created.  Need a table
Index: openacs-4/packages/cms/sql/postgresql/cms-widgets.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-widgets.sql,v
diff -u -r1.4 -r1.4.4.1
--- openacs-4/packages/cms/sql/postgresql/cms-widgets.sql	8 Jun 2001 01:44:53 -0000	1.4
+++ openacs-4/packages/cms/sql/postgresql/cms-widgets.sql	11 Feb 2003 17:07:33 -0000	1.4.4.1
@@ -3,7 +3,7 @@
 
 
 /* insert form widgets and params */
-create function inline_0 ()
+create or replace function inline_0 ()
 returns integer as '
 begin
 
@@ -94,7 +94,7 @@
 
 -- show errors
 
-create function inline_1 ()
+create or replace function inline_1 ()
 returns integer as '
 begin
 
@@ -123,7 +123,7 @@
 
 
 
-create function inline_2 ()
+create or replace function inline_2 ()
 returns integer as '
 begin
 
@@ -188,7 +188,7 @@
 
 /* Register attribute widgets for content_revision and image */
 
-create function inline_3 ()
+create or replace function inline_3 ()
 returns integer as '
 begin
   -- register form widgetes for content revision attributes
@@ -302,7 +302,7 @@
 
 
 
-create function inline_4 ()
+create or replace function inline_4 ()
 returns integer as '
 begin
 
Index: openacs-4/packages/cms/sql/postgresql/cms-workflow.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/cms-workflow.sql,v
diff -u -r1.11.4.1 -r1.11.4.2
--- openacs-4/packages/cms/sql/postgresql/cms-workflow.sql	21 Jan 2003 13:48:57 -0000	1.11.4.1
+++ openacs-4/packages/cms/sql/postgresql/cms-workflow.sql	11 Feb 2003 17:07:33 -0000	1.11.4.2
@@ -340,7 +340,7 @@
 
 -- create or replace package body content_workflow 
 -- function is_overdue
-create function content_workflow__is_overdue (integer)
+create or replace function content_workflow__is_overdue (integer)
 returns boolean as '
 declare
   p_task_id            alias for $1;  
@@ -368,7 +368,7 @@
 
 
 -- function is_overdue
-create function content_workflow__is_overdue (integer,varchar)
+create or replace function content_workflow__is_overdue (integer,varchar)
 returns boolean as '
 declare
   p_case_id                        alias for $1;  
@@ -393,7 +393,7 @@
 
 
 -- function get_holding_user_name
-create function content_workflow__get_holding_user_name (integer)
+create or replace function content_workflow__get_holding_user_name (integer)
 returns varchar as '
 declare
   p_task_id                        alias for $1;  
@@ -417,7 +417,7 @@
 
 
 
-create function content_workflow__get_first_place() returns varchar as '
+create or replace function content_workflow__get_first_place() returns varchar as '
 declare
     v_first_place wf_places.place_key%TYPE;
 begin
@@ -441,7 +441,7 @@
 end;' language 'plpgsql';
 
 -- function get_this_place
-create function content_workflow__get_this_place (varchar)
+create or replace function content_workflow__get_this_place (varchar)
 returns varchar as '
 declare
   p_transition_key                 alias for $1;  
@@ -470,7 +470,7 @@
 
 
 -- function get_next_place
-create function content_workflow__get_next_place (varchar)
+create or replace function content_workflow__get_next_place (varchar)
 returns varchar as '
 declare
   p_transition_key                 alias for $1;  
@@ -505,7 +505,7 @@
 
 
 -- function get_previous_place
-create function content_workflow__get_previous_place (varchar)
+create or replace function content_workflow__get_previous_place (varchar)
 returns varchar as '
 declare
   p_transition_key                 alias for $1;  
@@ -540,7 +540,7 @@
 
 
 -- procedure checkout
-create function content_workflow__checkout (integer,timestamp with time zone,integer,varchar,varchar)
+create or replace function content_workflow__checkout (integer,timestamp with time zone,integer,varchar,varchar)
 returns integer as '
 declare
   p_task_id                        alias for $1;  
@@ -634,7 +634,7 @@
 
 
 -- procedure checkin
-create function content_workflow__checkin (integer,integer,varchar,varchar)
+create or replace function content_workflow__checkin (integer,integer,varchar,varchar)
 returns integer as '
 declare
   p_task_id                        alias for $1;  
@@ -694,7 +694,7 @@
 
 
 -- procedure approve
-create function content_workflow__approve (integer,integer,varchar,varchar)
+create or replace function content_workflow__approve (integer,integer,varchar,varchar)
 returns integer as '
 declare
   p_task_id                        alias for $1;  
@@ -770,7 +770,7 @@
 
 
 -- procedure reject
-create function content_workflow__reject (integer,integer,varchar,varchar,varchar)
+create or replace function content_workflow__reject (integer,integer,varchar,varchar,varchar)
 returns integer as '
 declare
   p_task_id                        alias for $1;  
@@ -877,7 +877,7 @@
 
 
 -- procedure notify_of_checkout
-create function content_workflow__notify_of_checkout (integer,integer,integer,varchar)
+create or replace function content_workflow__notify_of_checkout (integer,integer,integer,varchar)
 returns integer as '
 declare
   p_task_id                        alias for $1;  
@@ -937,7 +937,7 @@
 
 
 -- function can_reject
-create function content_workflow__can_reject (integer,integer)
+create or replace function content_workflow__can_reject (integer,integer)
 returns boolean as '
 declare
   p_task_id                        alias for $1;  
@@ -965,7 +965,7 @@
 
 
 -- function can_approve
-create function content_workflow__can_approve (integer,integer)
+create or replace function content_workflow__can_approve (integer,integer)
 returns boolean as '
 declare
   p_task_id                        alias for $1;  
@@ -989,7 +989,7 @@
 
 
 -- function can_start
-create function content_workflow__can_start (integer,integer)
+create or replace function content_workflow__can_start (integer,integer)
 returns boolean as '
 declare
   p_task_id                        alias for $1;  
@@ -1013,7 +1013,7 @@
 
 
 -- function approve_string
-create function content_workflow__approve_string (integer,integer)
+create or replace function content_workflow__approve_string (integer,integer)
 returns varchar as '
 declare
   p_task_id                        alias for $1;  
@@ -1049,7 +1049,7 @@
 
 
 -- function count_finished_tasks
-create function content_workflow__count_finished_tasks (integer)
+create or replace function content_workflow__count_finished_tasks (integer)
 returns integer as '
 declare
   p_case_id                        alias for $1;  
@@ -1086,7 +1086,7 @@
 
 
 -- function count_unfinished_tasks
-create function content_workflow__count_unfinished_tasks (integer)
+create or replace function content_workflow__count_unfinished_tasks (integer)
 returns integer as '
 declare
   p_case_id                        alias for $1;  
@@ -1114,7 +1114,7 @@
 
 
 -- function is_active
-create function content_workflow__is_active (integer,varchar)
+create or replace function content_workflow__is_active (integer,varchar)
 returns boolean as '
 declare
   p_case_id                        alias for $1;  
@@ -1136,7 +1136,7 @@
 
 
 -- function is_finished
-create function content_workflow__is_finished (integer,varchar)
+create or replace function content_workflow__is_finished (integer,varchar)
 returns boolean as '
 declare
   p_case_id                        alias for $1;  
@@ -1186,7 +1186,7 @@
 
 
 -- function is_checked_out
-create function content_workflow__is_checked_out (integer,varchar)
+create or replace function content_workflow__is_checked_out (integer,varchar)
 returns boolean as '
 declare
   p_case_id                        alias for $1;  
@@ -1209,7 +1209,7 @@
 
 
 -- function is_checked_out
-create function content_workflow__is_checked_out (integer,varchar,integer)
+create or replace function content_workflow__is_checked_out (integer,varchar,integer)
 returns boolean as '
 declare
   p_case_id                        alias for $1;  
@@ -1235,7 +1235,7 @@
 
 
 -- function get_status
-create function content_workflow__get_status (integer,varchar)
+create or replace function content_workflow__get_status (integer,varchar)
 returns varchar as '
 declare
   p_case_id                        alias for $1;  
@@ -1283,7 +1283,7 @@
 
 
 -- function can_touch
-create function content_workflow__can_touch (integer,integer)
+create or replace function content_workflow__can_touch (integer,integer)
 returns boolean as '
 declare
   p_item_id                        alias for $1;  
@@ -1342,7 +1342,7 @@
 
 
 -- function unfinished_workflow_exists
-create function content_workflow__unfinished_workflow_exists (integer)
+create or replace function content_workflow__unfinished_workflow_exists (integer)
 returns boolean as '
 declare
   p_item_id                        alias for $1;  
Index: openacs-4/packages/cms/sql/postgresql/rel-test.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/cms/sql/postgresql/rel-test.sql,v
diff -u -r1.2 -r1.2.4.1
--- openacs-4/packages/cms/sql/postgresql/rel-test.sql	22 May 2001 04:44:57 -0000	1.2
+++ openacs-4/packages/cms/sql/postgresql/rel-test.sql	11 Feb 2003 17:07:33 -0000	1.2.4.1
@@ -18,7 +18,7 @@
                  check (direction in ('in', 'out'))
 ); 
 
-create function inline_0 () returns integer as '
+create or replace function inline_0 () returns integer as '
 declare
   attr_id       integer;
 begin
@@ -95,7 +95,7 @@
   weight_b       integer not null
 ); 
 
-create function inline_1 () returns integer as '
+create or replace function inline_1 () returns integer as '
 declare
   attr_id       integer;
 begin
Fisheye: Tag 1.1 refers to a dead (removed) revision in file `openacs-4/packages/cms/sql/postgresql/upgrade/upgrade-4.6-4.6.1.sql'.
Fisheye: No comparison available.  Pass `N' to diff?
Index: openacs-4/packages/file-storage/tcl/file-storage-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/tcl/file-storage-procs-postgresql.xql,v
diff -u -r1.29.2.1 -r1.29.2.2
--- openacs-4/packages/file-storage/tcl/file-storage-procs-postgresql.xql	21 Jan 2003 13:50:16 -0000	1.29.2.1
+++ openacs-4/packages/file-storage/tcl/file-storage-procs-postgresql.xql	11 Feb 2003 17:09:46 -0000	1.29.2.2
@@ -45,31 +45,29 @@
     <fullquery name="fs::get_folder_contents.select_folder_contents">
         <querytext>
 
--- we use $ n_past-days instead of :n_past_days because the pgdriver
--- bind variable emulation puts single-quotes around the n_past_days
--- integer. Postgresql tries to turn '-1' into a date datatype
--- so now()-'-1' fails but now()- interval '-1' works fine.
+            select fs_objects.object_id,
+                   fs_objects.name,
+                   fs_objects.live_revision,
+                   fs_objects.type,
+                   to_char(fs_objects.last_modified, 'Month DD YYYY HH24:MI') as last_modified,
+                   fs_objects.content_size,
+                   fs_objects.url,
+                   fs_objects.key,
+                   fs_objects.sort_key,
+                   fs_objects.file_upload_name,
+                   case when fs_objects.last_modified >= (now() - interval '$n_past_days days') then 1 else 0 end as new_p,
+                   acs_permission__permission_p(fs_objects.object_id, :user_id, 'admin') as admin_p,
+                   acs_permission__permission_p(fs_objects.object_id, :user_id, 'delete') as delete_p,
+                   acs_permission__permission_p(fs_objects.object_id, :user_id, 'write') as write_p
+            from fs_objects
+            where fs_objects.parent_id = :folder_id
+              and exists (select 1
+                   from acs_object_party_privilege_map m
+                   where m.object_id = fs_objects.object_id
+                     and m.party_id = :user_id
+                     and m.privilege = 'read')
+            order by fs_objects.sort_key, fs_objects.name
 
-	select fc.*
-            from (select fs_objects.object_id,
-                         fs_objects.name,
-                         fs_objects.live_revision,
-                         fs_objects.type,
-                         to_char(fs_objects.last_modified, 'Month DD YYYY HH24:MI') as last_modified,
-                         fs_objects.content_size,
-                         fs_objects.url,
-                         fs_objects.key,
-                         fs_objects.sort_key,
-                         fs_objects.file_upload_name,
-                         case when fs_objects.last_modified >= (now() - interval '$n_past_days days') then 1 else 0 end as new_p,
-                         acs_permission__permission_p(fs_objects.object_id, :user_id, 'admin') as admin_p,
-                         acs_permission__permission_p(fs_objects.object_id, :user_id, 'delete') as delete_p,
-                         acs_permission__permission_p(fs_objects.object_id, :user_id, 'write') as write_p
-                  from fs_objects
-                  where fs_objects.parent_id = :folder_id) fc
-            where 't' = (select acs_permission__permission_p(fc.object_id, :user_id, 'read') from dual)
-            order by fc.sort_key,
-                     fc.name
         </querytext>
     </fullquery>
 
Index: openacs-4/packages/file-storage/www/folder-chunk-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/file-storage/www/folder-chunk-postgresql.xql,v
diff -u -r1.1.2.2 -r1.1.2.3
--- openacs-4/packages/file-storage/www/folder-chunk-postgresql.xql	4 Feb 2003 12:15:31 -0000	1.1.2.2
+++ openacs-4/packages/file-storage/www/folder-chunk-postgresql.xql	11 Feb 2003 17:11:30 -0000	1.1.2.3
@@ -20,4 +20,4 @@
 	          order by sort_key, name
         </querytext>
     </fullquery>
-</queryset>
\ No newline at end of file
+</queryset>