-- -- /www/doc/sql/upgrade-3.1-3.2.sql -- -- Script to upgrade an ACS 3.1 database to ACS 3.2 -- -- upgrade-3.1-3.2.sql,v 3.17.2.24 2000/03/28 09:41:10 carsten Exp -- -- BEGIN SECURITY -- create table sec_sessions ( -- Unique ID (don't care if everyone knows this) session_id integer primary key, user_id integer references users, -- A secret used for unencrypted connections token varchar(50) not null, -- A secret used for encrypted connections only. not generated until needed secure_token varchar(50), browser_id integer not null, -- Make sure all hits in this session are from same host last_ip varchar(50) not null, -- When was the last hit from this session? (seconds since the epoch) last_hit integer not null ); create table sec_login_tokens ( -- A table to track tokens assigned for permanent login. The login_token -- is isomorphic to the password, i.e., the user can use the login_token -- to log back in. user_id integer references users not null, password varchar(30) not null, login_token varchar(50) not null, primary key(user_id, password) ); -- When a user changes his password, delete any login tokens associated -- with the old password. create function trig_users_update_login_token() returns opaque as ' DECLARE BEGIN delete from sec_login_tokens where user_id= NEW.user_id and password!= NEW.password; return NEW; END; ' language 'plpgsql'; create trigger users_update_login_token before update on users for each row execute procedure trig_users_update_login_token(); create table sec_session_properties ( session_id integer references sec_sessions not null, module varchar(50) not null, property_name varchar(50) not null, property_value varchar(4000), -- transmitted only across secure connections? secure_p char(1) check(secure_p in ('t','f')), primary key(session_id, module, property_name), foreign key(session_id) references sec_sessions on delete cascade ); create table sec_browser_properties ( browser_id integer not null, module varchar(50) not null, property_name varchar(50) not null, property_value clob, -- transmitted only across secure connections? secure_p char(1) check(secure_p in ('t','f')), primary key(browser_id, module, property_name) ); create sequence sec_id_seq; create function sec_rotate_last_visit(integer, integer) returns integer as ' DECLARE v_browser_id alias for $1; v_time alias for $2; BEGIN delete from sec_browser_properties where browser_id = v_browser_id and module = ''acs'' and property_name = ''second_to_last_visit''; update sec_browser_properties set property_name = ''second_to_last_visit'' where module = ''acs'' and property_name = ''last_visit'' and browser_id = v_browser_id; insert into sec_browser_properties(browser_id, module, property_name, property_value, secure_p) values(v_browser_id, ''acs'', ''last_visit'', v_time::char, ''f''); return 1; end; ' language 'plpgsql'; -- END SECURITY -- -- BEGIN USER GROUPS -- -- Drop user_group_map's primary key (user_id + group_id), -- and replace it with a unique constraint on user_id + -- group_id + role. alter table user_group_map drop primary key; alter table user_group_map add unique (user_id, group_id, role); -- Drop user_group_type_member_fields's primary key (user_id + -- group_id), and replace it with a unique constraint on user_id + -- group_id + role, which is a new column. alter table user_group_type_member_fields add (role varchar(200)); alter table user_group_type_member_fields drop primary key; alter table user_group_type_member_fields add unique (group_type, role, field_name); -- Rename user_group_regdate trigger to user_group_approved_p_tr drop trigger user_group_regdate; create or replace trigger user_group_approved_p_tr before insert on user_groups for each row declare group_type_row user_group_types%ROWTYPE; begin if :new.approved_p is null then select * into group_type_row from user_group_types ugt where ugt.group_type = :new.group_type; if group_type_row.approval_policy = 'open' then :new.approved_p := 't'; else :new.approved_p := 'f'; end if; end if; end; / show errors -- new proc ad_user_has_role_p create or replace function ad_user_has_role_p (v_user_id IN user_group_map.user_id%TYPE, v_group_id IN user_group_map.group_id%TYPE, v_role IN user_group_map.role%TYPE) return char IS ad_user_has_role_p char(1); BEGIN -- maybe we should check the validity of user_id and group_id; -- we're not doing it for now, because it would slow this function -- down with 2 extra queries select decode(count(*), 0, 'f', 't') into ad_user_has_role_p from user_group_map where user_id = v_user_id and group_id = v_group_id and role = v_role; return ad_user_has_role_p; END ad_user_has_role_p; / show errors -- Replace superfluous triggers with default values alter table user_groups modify ( registration_date date default sysdate ); drop trigger user_group_map_regdate; alter table user_group_map modify ( registration_date date default sysdate ); drop trigger user_group_roles_creation_date; alter table user_group_roles modify ( creation_date date default sysdate ); drop trigger user_group_actions_create_date; alter table user_group_actions modify ( creation_date date default sysdate ); drop trigger user_gr_action_role_map_date; alter table user_group_action_role_map modify ( creation_date date default sysdate ); drop trigger user_group_map_queue_date; alter table user_group_map_queue modify ( queue_date date default sysdate ); -- END USER GROUPS -- -- BEGIN DOWNLOAD MODULE -- -- Change the data type of version column from number to varchar alter table download_versions add ( temp_version varchar(30)); update download_versions set temp_version = to_char(version) where version is not null; alter table download_versions drop column version; alter table download_versions add ( version varchar(30)); update download_versions set version = temp_version; alter table download_versions drop column temp_version; -- Add new columns alter table download_versions add ( version_description varchar(4000), version_html_p char(1) default 'f' check (version_html_p in ('t','f')) ); commit; -- END DOWNLOAD MODULE -- -- BEGIN INTRANET MODULE -- -- add partner status information to the intranet create sequence im_partner_status_id_seq start with 1; create table im_partner_status ( partner_status_id integer primary key, partner_status varchar(100) not null unique, display_order integer default 1 ); alter table im_partners add partner_status_id references im_partner_status; -- populate the intranet partner status table insert into im_partner_status (partner_status_id, partner_status, display_order) values (im_partner_status_id_seq.nextVal, 'Targeted', 1); insert into im_partner_status (partner_status_id, partner_status, display_order) values (im_partner_status_id_seq.nextVal, 'In Discussion', 2); insert into im_partner_status (partner_status_id, partner_status, display_order) values (im_partner_status_id_seq.nextVal, 'Active', 3); insert into im_partner_status (partner_status_id, partner_status, display_order) values (im_partner_status_id_seq.nextVal, 'Announced', 4); insert into im_partner_status (partner_status_id, partner_status, display_order) values (im_partner_status_id_seq.nextVal, 'Dormant', 5); insert into im_partner_status (partner_status_id, partner_status, display_order) values (im_partner_status_id_seq.nextVal, 'Dead', 6); alter table im_employee_info add referred_by references users; create index im_employee_info_referred_idx on im_employee_info(referred_by); create or replace function im_project_ticket_project_id ( v_group_id IN integer ) RETURN integer IS v_project_id ticket_projects.project_id%TYPE; BEGIN v_project_id := 0; BEGIN select project_id into v_project_id from ticket_projects where group_id = v_group_id; EXCEPTION WHEN OTHERS THEN NULL; END; return v_project_id; END; / show errors; begin user_group_add ('intranet', 'Partners', 'partner', 'f'); user_group_add ('intranet', 'Authorized Users', 'authorized_users', 'f'); end; / show errors; alter table im_employee_info add ( featured_employee_approved_p char(1) constraint featured_employee_p_con check(featured_employee_approved_p in ('t','f')), featured_employee_approved_by integer references users, featured_employee_blurb clob, featured_employee_blurb_html_p char(1) default 'f' constraint featured_emp_blurb_html_p_con check (featured_employee_blurb_html_p in ('t','f')) ); -- END INTRANET MODULE -- -- BEGIN EVENTS MODULE -- -- create a procedure for initializing a new sequence initialized -- to start with values from another sequence. create or replace procedure init_sequence (new_seq IN varchar, old_seq IN varchar) IS i_seq_val integer; tmp_seq_val integer; sql_stmt varchar(500); i integer; BEGIN -- get the old sequence's value sql_stmt := 'select ' || old_seq || '.nextval from dual'; EXECUTE IMMEDIATE sql_stmt INTO i_seq_val; -- set the new sequence to be the old sequence's value i := 0; FOR i IN 0..i_seq_val LOOP EXECUTE IMMEDIATE 'select ' || new_seq || '.nextval from dual' INTO tmp_seq_val; END LOOP; END init_sequence; / show errors; --------------------------------------------- -- create the new events module data model --------------------------------------------- -- we store the ISO code in lower case, e.g,. 'us' -- if detail_url does not start with "HTTP://" then we assume -- it is a stub for information on our server and we grab it -- from the file system, starting at [ns_info pageroot] create or replace procedure administration_subgroup_add (pretty_name IN varchar, v_short_name IN varchar, v_module IN varchar, v_submodule IN varchar, v_multi_role_p IN varchar, v_url IN varchar, v_parent_module IN varchar) IS v_group_id integer; n_administration_groups integer; v_system_user_id integer; v_parent_id integer; BEGIN if v_submodule is null then select count(group_id) into n_administration_groups from administration_info where module = v_module and submodule is null; else select count(group_id) into n_administration_groups from administration_info where module = v_module and submodule = v_submodule; end if; if n_administration_groups = 0 then -- call procedure defined in community-core.sql to get system user v_system_user_id := system_user_id; select user_group_sequence.nextval into v_group_id from dual; insert into user_groups (group_id, group_type, short_name, group_name, creation_user, creation_ip_address, approved_p, existence_public_p, new_member_policy, multi_role_p) values (v_group_id, 'administration', v_short_name, pretty_name, v_system_user_id, '0.0.0.0', 't', 'f', 'closed', v_multi_role_p); insert into administration_info (group_id, module, submodule, url) values (v_group_id, v_module, v_submodule, v_url); end if; Begin select ai.group_id into v_parent_id from administration_info ai, user_groups ug where ai.module = v_parent_module and ai.group_id != v_group_id and ug.group_id = ai.group_id and ug.parent_group_id is null; Exception when others then null; End; update user_groups set parent_group_id = v_parent_id where group_id = v_group_id; end; / show errors --- create the administration group for the Events module begin administration_group_add ('Events Administration', 'events', 'events', '', 'f', '/admin/events/'); end; / -- create a group type of "events" insert into user_group_types (group_type, pretty_name, pretty_plural, approval_policy, group_module_administration) values ('events_group', 'Event', 'Events', 'closed', 'full'); create table events_group_info ( group_id primary key references user_groups ); -- can't ever delete an event/activity because it might have been -- ordered and therefore the row in events_registrations would be hosed -- so we flag it create sequence events_activity_id_sequence; -- the activities create table events_activities ( activity_id integer primary key, -- activities are owned by user groups group_id integer references user_groups, user_id integer references users, creator_id integer not null references users, short_name varchar(100) not null, default_price number default 0 not null, currency char(3) default 'USD', description clob, -- Is this activity occurring? If not, we can't assign -- any new events to it. available_p char(1) default 't' check (available_p in ('t', 'f')), deleted_p char(1) default 'f' check (deleted_p in ('t', 'f')), detail_url varchar(256) -- URL for more details, ); create sequence events_venues_id_sequence; -- where the events occur create table events_venues ( venue_id integer primary key, venue_name varchar(200) not null, address1 varchar(100), address2 varchar(100), city varchar(100) not null, usps_abbrev char(2), postal_code varchar(20), iso char(2) default 'us' references country_codes, time_zone varchar(50), needs_reserve_p char(1) default 'f' check (needs_reserve_p in ('t', 'f')), max_people number, description clob ); create sequence events_event_id_sequence; -- the events (instances of activities) create table events_events ( event_id integer not null primary key, activity_id integer not null references events_activities, venue_id integer not null references events_venues, -- the user group that is created for this event's registrants group_id integer not null references user_groups, creator_id integer not null references users, -- HTML to be displayed after a successful order. display_after varchar(4000), -- Date and time. start_time date not null, end_time date not null, reg_deadline date not null, -- An event may have been cancelled. available_p char(1) default 't' check (available_p in ('t', 'f')), deleted_p char(1) default 'f' check (deleted_p in ('t', 'f')), max_people number, -- can someone cancel his registration? reg_cancellable_p char(1) default 't' check (reg_cancellable_p in ('t', 'f')), -- does a registration need approval to become finalized? reg_needs_approval_p char(1) default 'f' check (reg_needs_approval_p in ('t', 'f')), -- notes for doing av setup av_note clob, -- notes for catering refreshments_note clob, -- extra info about this event additional_note clob, -- besides the web, is there another way to register? alternative_reg clob, check (start_time < end_time), check (reg_deadline <= start_time) ); -- Each activity can have default custom fields registrants should enter. create table events_activity_fields ( activity_id not null references events_activities, column_name varchar(30) not null, pretty_name varchar(50) not null, -- something generic and suitable for handing to AOLserver, -- e.g., boolean or text column_type varchar(50) not null, -- something nitty gritty and Oracle-specific, e.g., -- char(1) instead of boolean -- things like "not null" column_actual_type varchar(100) not null, column_extra varchar(100), -- Sort key for display of columns. sort_key integer not null ); -- Each event can have custom fields registrants should enter. The -- event's custom fields are actually stored in the table, -- event_{$event_id}_info. For example, the event with event_id == 5 -- would have a corresponding table of event_5_info. Furthermore, this -- table will contain a "user_id not null references users" column -- This table describes the columns that go into event_{$event_id}_info create table events_event_fields ( event_id not null references events_events, column_name varchar(30) not null, pretty_name varchar(50) not null, -- something generic and suitable for handing to AOLserver, -- e.g., boolean or text column_type varchar(50) not null, -- something nitty gritty and Oracle-specific, e.g., -- char(1) instead of boolean -- things like "not null" column_actual_type varchar(100) not null, column_extra varchar(100), -- Sort key for display of columns. sort_key integer not null ); -- the organizers for events create table events_organizers_map ( event_id integer not null references events_events, user_id integer not null references users, role varchar(200) default 'organizer' not null, responsibilities clob ); create sequence events_price_id_sequence; create table events_prices ( price_id integer primary key, event_id integer not null references events_events, -- e.g., "Developer", "Student" description varchar(100) not null, -- we also store the price here too in case someone doesn't want -- to use the ecommerce module but still wants to have prices price number not null, -- This is for hooking up to ecommerce. -- Each product is a different price for this event. For example, -- student price and normal price products for an event. -- product_id integer references ec_products, -- prices may be different for early, normal, late, on-site -- admission, -- depending on the date expire_date date not null, available_date date not null ); create sequence events_orders_id_sequence; create table events_orders ( order_id integer not null primary key, -- ec_order_id integer references ec_orders, -- the person who made the order user_id integer not null references users, paid_p char(1) default null check (paid_p in ('t', 'f', null)), payment_method varchar(50), confirmed_date date, price_charged number, -- the date this registration was refunded, if it was refunded refunded_date date, price_refunded number, ip_address varchar(50) not null ); create sequence events_reg_id_sequence; create table events_registrations( -- Goes into table at confirmation time: reg_id integer not null primary key, order_id integer not null references events_orders, price_id integer not null references events_prices, -- the person registered for this reg_id (may not be the person -- who made the order) user_id integer not null references users, -- reg_states: pending, shipped, canceled, refunded --pending: waiting for approval --shipped: registration all set --canceled: registration canceled --waiting: registration is wait-listed reg_state varchar(50) not null check (reg_state in ('pending', 'shipped', 'canceled', 'waiting')), -- when the registration was made reg_date date, -- when the registration was shipped shipped_date date, org varchar(4000), title_at_org varchar(4000), attending_reason clob, where_heard varchar(4000), -- does this person need a hotel? need_hotel_p char(1) default 'f' check (need_hotel_p in ('t', 'f')), -- does this person need a rental car? need_car_p char(1) default 'f' check (need_car_p in ('t', 'f')), -- does this person need airfare? need_plane_p char(1) default 'f' check (need_plane_p in ('t', 'f')), comments clob ); -- trigger for recording when a registration ships create or replace trigger event_ship_date_trigger before insert or update on events_registrations for each row when (old.reg_state <> 'shipped' and new.reg_state = 'shipped') begin :new.shipped_date := sysdate; end; / show errors -- create a view that shows order states based upon each order's -- registrations. The order states are: -- void: All registrations canceled -- incomplete: This order is not completely fulfilled--some registrations -- are either canceled, waiting, or pending -- fulfilled: This order is completely fulfilled create or replace view events_orders_states as select o.*, o_states.order_state from events_orders o, (select order_id, decode (floor(avg (decode (reg_state, 'canceled', 0, 'waiting', 1, 'pending', 2, 'shipped', 3, 0))), 0, 'canceled', 1, 'incomplete', 2, 'incomplete', 3, 'fulfilled', 'void') as order_state from events_registrations group by order_id) o_states where o_states.order_id = o.order_id; create or replace view events_reg_not_canceled as select * from events_registrations where reg_state <> 'canceled'; create or replace view events_reg_canceled as select * from events_registrations where reg_state = 'canceled'; create or replace view events_reg_shipped as select * from events_registrations where reg_state = 'shipped'; create sequence events_fs_file_id_seq start with 1; create table events_file_storage ( file_id integer primary key, file_title varchar(300), file_content blob not null, client_file_name varchar(500), file_type varchar(100), file_extension varchar(50), on_which_table varchar(100) not null, on_what_id integer not null, -- the size (kB) of the fileument file_size integer, created_by references users, creation_ip_address varchar(100), creation_date date default sysdate ); create index events_file_storage_id_idx on events_file_storage(on_which_table, on_what_id); -- Sync up the new sequences with the old ones. execute init_sequence('events_activity_id_sequence', 'evreg_activity_id_sequence'); execute init_sequence('events_venues_id_sequence', 'evreg_venues_id_sequence'); execute init_sequence('events_event_id_sequence', 'evreg_event_id_sequence'); ---------------------------------- -- copy the old events data ---------------------------------- --function for creating a user group for an event create or replace function create_event_group( event_id_in integer ) return integer IS event_group_name varchar(100); event_short_name varchar(100); event_group_id integer; event_start varchar(25); short_name varchar(100); city varchar(100); usps_abbrev char(2); iso char(2); pretty_location varchar(100); BEGIN -- select -- to_char(e.start_time, 'YYYY-MM-DD HH:MM:SS') into event_start, -- a.short_name into short_name, -- v.city into city, -- v.usps_abbrev into usps_abbrev, -- v.iso into iso select to_char(e.start_time, 'YYYY-MM-DD HH:MM:SS'), a.short_name, v.city, v.usps_abbrev, v.iso into event_start, short_name, city, usps_abbrev, iso from evreg_events e, evreg_activities a, evreg_venues v where a.activity_id = e.activity_id and v.venue_id = e.venue_id and e.event_id = event_id_in; IF iso = 'us' THEN pretty_location := city || ', ' || usps_abbrev; ELSE pretty_location := city || ', ' || iso; END IF; event_group_name := short_name || ' in ' || pretty_location || ' on ' || event_start; event_short_name := short_name_from_group_name(event_group_name); --create the user group now user_group_add('events_group', event_group_name, event_short_name, 't'); --get the group id select group_id into event_group_id from user_groups where short_name = event_short_name; return event_group_id; end create_event_group; / show errors --procedure for creating the appropriate prices for events create or replace procedure create_event_prices IS price_avail_time date; cursor c1 is select event_id, end_time, start_time from events_events; BEGIN FOR e IN c1 LOOP --see what to put for when this price is available IF sysdate < e.start_time THEN --this event hasn't taken place yet, so the price is --available now price_avail_time := sysdate; ELSE --event has already taken place, so arbitrarily --use the start time - 1 day price_avail_time := e.start_time - 1; END IF; INSERT into events_prices (price_id, event_id, description, price, expire_date, available_date) VALUES (events_price_id_sequence.nextval, e.event_id, 'Normal Price', 0, e.end_time, price_avail_time); END LOOP; END create_event_prices; / show errors; --procedure to copy the registrations over create or replace procedure copy_registrations IS i_order_id integer; v_reg_state varchar(50); i_price_id integer; cursor c1 is select event_id, user_id, paid_p, confirmed_date, ip_address, order_state, org, title_at_org, attending_reason, where_heard, need_hotel_p, need_car_p, need_plane_p, comments, canceled_p from evreg_orders; BEGIN FOR o in c1 LOOP --this depends on events_events having the same --event_id's as evreg_events select price_id into i_price_id from events_prices where event_id = o.event_id; --create the event order select events_orders_id_sequence.nextval into i_order_id from dual; INSERT into events_orders (order_id, user_id, paid_p, confirmed_date, ip_address) VALUES (i_order_id, o.user_id, o.paid_p, o.confirmed_date, o.ip_address); --figure out the reg_state IF o.canceled_p = 't' THEN v_reg_state := 'canceled'; ELSIF o.order_state = 'shipped' THEN v_reg_state := 'shipped'; ELSE v_reg_state := 'pending'; END IF; --copy the registration INSERT into events_registrations (reg_id, order_id, price_id, user_id, reg_state, org, title_at_org, attending_reason, where_heard, need_hotel_p, need_car_p, need_plane_p, reg_date) VALUES (events_reg_id_sequence.nextval, i_order_id, i_price_id, o.user_id, v_reg_state, o.org, o.title_at_org, o.attending_reason, o.where_heard, o.need_hotel_p, o.need_car_p, o.need_plane_p, o.confirmed_date); END LOOP; END copy_registrations; / show errors; insert into events_activities (activity_id, group_id, creator_id, short_name, default_price, currency, description, available_p, deleted_p, detail_url) select activity_id, group_id, creator_id, short_name, 0, 'USD', description, available_p, 'f', detail_url from evreg_activities; insert into events_venues (venue_id, venue_name, address1, address2, city, usps_abbrev, postal_code, iso, needs_reserve_p, max_people, description) select venue_id, venue_name, address1, address2, city, usps_abbrev, postal_code, iso, needs_reserve_p, max_people, description from evreg_venues; insert into events_events (event_id, activity_id, venue_id, display_after, max_people, av_note, refreshments_note, additional_note, start_time, end_time, reg_deadline, reg_cancellable_p, group_id, reg_needs_approval_p, creator_id) SELECT event_id, activity_id, venue_id, display_after, max_people, av_note, refreshments_note, additional_note, start_time, end_time, start_time, 't', create_event_group(event_id), 'f', system_user_id from evreg_events; insert into events_organizers_map (event_id, user_id, role, responsibilities) select event_id, user_id, role, responsibilities from evreg_organizers_map; execute create_event_prices(); execute copy_registrations(); INSERT into events_file_storage (file_id, file_title, file_content, client_file_name, file_type, file_extension, on_which_table, on_what_id, file_size, created_by, creation_ip_address, creation_date) SELECT file_id, file_title, file_content, client_file_name, file_type, file_extension, on_which_table, on_what_id, file_size, created_by, creation_ip_address, creation_date FROM evreg_file_storage; ------------------------------------------ -- delete the old events data model ------------------------------------------ drop sequence evreg_file_storage_file_id_seq; drop table evreg_file_storage; drop sequence evreg_order_id_sequence; drop view evreg_orders_not_canceled; drop view evreg_orders_canceled; drop table evreg_orders; drop table evreg_organizers_map; drop sequence evreg_event_id_sequence; drop table evreg_events; drop table evreg_venues; drop sequence evreg_venues_id_sequence; drop table evreg_activities; drop sequence evreg_activity_id_sequence; --drop the helper procedures/function drop procedure init_sequence; drop function create_event_group; drop procedure create_event_prices; drop procedure copy_registrations; -- END EVENTS MODULE -- -- BEGIN GENERAL-PERMISSIONS -- -- The general-permissions data model has changed substantially, -- going from two tables to just one. -- First, we create a temporary table into which we migrate the -- legacy data. Then, we drop all the existing data model, -- create the new one (incl. triggers, view, package), copy data -- from the temporary table into the new table, and finally -- drop the temporary table. -- create table general_permissions_temp ( permission_id integer not null primary key, on_what_id integer not null, on_which_table varchar(30) not null, scope varchar(20), user_id references users, group_id references user_groups, role varchar(200), permission_type varchar(20) not null, check ((scope = 'user' and user_id is not null and group_id is null and role is null) or (scope = 'group_role' and user_id is null and group_id is not null and role is not null) or (scope = 'group' and user_id is null and group_id is not null and role is null) or (scope in ('registered_users', 'all_users') and user_id is null and group_id is null and role is null)), unique (on_what_id, on_which_table, scope, user_id, group_id, role, permission_type) ); declare v_scope general_permissions_temp.scope%TYPE; begin -- Turn each row in general_permissions into as many as three rows -- in general_permissions_temp: public_read_p, public_write_p, and/or -- public_comment_p. For all, the scope will be 'all_users'. -- for perm in (select * from general_permissions) loop if perm.public_read_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, 'all_users', 'read'); end if; if perm.public_write_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, 'all_users', 'write'); end if; if perm.public_comment_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, 'all_users', 'comment'); end if; end loop; -- Turn each row in permissions_ug_map into as many as four rows -- in general_permissions_temp: read_p, write_p, comment_p, and/or -- owner_p (which we will turn into 'administer' permission_type). -- We will need to determine the scope for each row. -- for perm in (select p.on_what_id, p.on_which_table, pgm.user_id, pgm.group_id, pgm.role, pgm.read_p, pgm.write_p, pgm.comment_p, pgm.owner_p from permissions_ug_map pgm, general_permissions p where pgm.permissions_id = p.permissions_id) loop if perm.user_id is not null then v_scope := 'user'; elsif perm.group_id is not null then if perm.role is not null then v_scope := 'group_role'; else v_scope := 'group'; end if; end if; if perm.read_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, user_id, group_id, role, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, perm.user_id, perm.group_id, perm.role, v_scope, 'read'); end if; if perm.write_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, user_id, group_id, role, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, perm.user_id, perm.group_id, perm.role, v_scope, 'write'); end if; if perm.comment_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, user_id, group_id, role, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, perm.user_id, perm.group_id, perm.role, v_scope, 'comment'); end if; if perm.owner_p = 't' then insert into general_permissions_temp (permission_id, on_what_id, on_which_table, user_id, group_id, role, scope, permission_type) values (gp_id_sequence.nextval, perm.on_what_id, perm.on_which_table, perm.user_id, perm.group_id, perm.role, v_scope, 'administer'); end if; end loop; end; / show errors drop table permissions_ug_map; drop table general_permissions; drop table perm_change_state_rowids; create table general_permissions ( permission_id integer not null primary key, on_what_id integer not null, on_which_table varchar(30) not null, scope varchar(20), user_id references users, group_id references user_groups, role varchar(200), permission_type varchar(20) not null, check ((scope = 'user' and user_id is not null and group_id is null and role is null) or (scope = 'group_role' and user_id is null and group_id is not null and role is not null) or (scope = 'group' and user_id is null and group_id is not null and role is null) or (scope in ('registered_users', 'all_users') and user_id is null and group_id is null and role is null)), unique (on_what_id, on_which_table, scope, user_id, group_id, role, permission_type) ); -- This trigger normalizes values in the on_which_table column to -- be all lowercase. This makes it easier to implement a case- -- insensitive API (since function-based indexes do not seem to -- work as advertised in Oracle 8.1.5). Just make sure to call -- LOWER whenever constructing a criterion involving -- on_which_table. -- create or replace trigger gp_on_which_table_tr before insert or update on general_permissions for each row begin :new.on_which_table := lower(:new.on_which_table); end gp_on_which_table_tr; / show errors -- This trigger normalizes values in the permission_type column to -- be all lowercase. This makes it easier to implement a case- -- insensitive API (since function-based indexes do not seem to -- work as advertised in Oracle 8.1.5). Just make sure to call -- LOWER whenever constructing a criterion involving -- permission_type. -- create or replace trigger gp_permission_type_tr before insert or update on general_permissions for each row begin :new.permission_type := lower(:new.permission_type); end gp_permission_type_tr; / show errors -- This view makes it simple to fetch a standard set of -- permission flags (true or false) for arbitrary rows -- in the database. -- create or replace view general_permissions_grid as select p.on_what_id, p.on_which_table, p.scope, p.user_id, p.group_id, p.role, decode(sum(decode(p.permission_type, 'read', 1, 0)), 0, 'f', 't') as read_permission_p, decode(sum(decode(p.permission_type, 'comment', 1, 0)), 0, 'f', 't') as comment_permission_p, decode(sum(decode(p.permission_type, 'write', 1, 0)), 0, 'f', 't') as write_permission_p, decode(sum(decode(p.permission_type, 'administer', 1, 0)), 0, 'f', 't') as administer_permission_p from general_permissions p group by p.on_what_id, p.on_which_table, p.scope, p.user_id, p.group_id, p.role; create or replace package ad_general_permissions as -- Returns 't' if the specified user has the specified permission on -- the specified database row. -- function user_has_row_permission_p ( v_user_id general_permissions.user_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return char; function grant_permission_to_user ( v_user_id general_permissions.user_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function grant_permission_to_role ( v_group_id general_permissions.group_id%TYPE, v_role general_permissions.role%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function grant_permission_to_group ( v_group_id general_permissions.group_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function grant_permission_to_reg_users ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function grant_permission_to_all_users ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; procedure revoke_permission ( v_permission_id general_permissions.permission_id%TYPE ); function user_permission_id ( v_user_id general_permissions.user_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function group_role_permission_id ( v_group_id general_permissions.group_id%TYPE, v_role general_permissions.role%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function group_permission_id ( v_group_id general_permissions.group_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function reg_users_permission_id ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; function all_users_permission_id ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE; procedure copy_permissions ( v_old_on_what_id general_permissions.on_what_id%TYPE, v_new_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE, v_user_id1 general_permissions.user_id%TYPE, v_user_id2 general_permissions.user_id%TYPE ); end ad_general_permissions; / show errors create or replace package body ad_general_permissions as function user_has_row_permission_p ( v_user_id general_permissions.user_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return char is user_has_row_permission_p char(1) := 'f'; begin -- Return true if the user is a system administrator -- or if the permission has been granted to at least one of: -- -- * all users -- * registered users if the user is logged in -- * the user directly -- * a role in a user group that the user plays -- * an entire user group of which the user is a member -- select ad_group_member_p(v_user_id, system_administrator_group_id) into user_has_row_permission_p from dual; if user_has_row_permission_p = 'f' then select decode(count(*), 0, 'f', 't') into user_has_row_permission_p from general_permissions gp where gp.on_what_id = v_on_what_id and gp.on_which_table = lower(v_on_which_table) and gp.permission_type = lower(v_permission_type) and ((gp.scope = 'all_users') or (gp.scope = 'registered_users' and v_user_id > 0) or (gp.scope = 'group' and exists (select 1 from user_group_map ugm where ugm.user_id = v_user_id and ugm.group_id = gp.group_id)) or (gp.scope = 'group_role' and exists (select 1 from user_group_map ugm where ugm.user_id = v_user_id and ugm.group_id = gp.group_id and ugm.role = gp.role)) or (gp.scope = 'user' and gp.user_id = v_user_id)) and rownum < 2; end if; return user_has_row_permission_p; end user_has_row_permission_p; function grant_permission_to_user ( v_user_id general_permissions.user_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select gp_id_sequence.nextval into v_permission_id from dual; insert into general_permissions (permission_id, on_what_id, on_which_table, scope, user_id, permission_type) values (v_permission_id, v_on_what_id, v_on_which_table, 'user', v_user_id, v_permission_type); return v_permission_id; end grant_permission_to_user; function grant_permission_to_role ( v_group_id general_permissions.group_id%TYPE, v_role general_permissions.role%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select gp_id_sequence.nextval into v_permission_id from dual; insert into general_permissions (permission_id, on_what_id, on_which_table, scope, group_id, role, permission_type) values (v_permission_id, v_on_what_id, v_on_which_table, 'group_role', v_group_id, v_role, v_permission_type); return v_permission_id; end grant_permission_to_role; function grant_permission_to_group ( v_group_id general_permissions.group_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select gp_id_sequence.nextval into v_permission_id from dual; insert into general_permissions (permission_id, on_what_id, on_which_table, scope, group_id, permission_type) values (v_permission_id, v_on_what_id, v_on_which_table, 'group', v_group_id, v_permission_type); return v_permission_id; end grant_permission_to_group; function grant_permission_to_reg_users ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select gp_id_sequence.nextval into v_permission_id from dual; insert into general_permissions (permission_id, on_what_id, on_which_table, scope, permission_type) values (v_permission_id, v_on_what_id, v_on_which_table, 'registered_users', v_permission_type); return v_permission_id; end grant_permission_to_reg_users; function grant_permission_to_all_users ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select gp_id_sequence.nextval into v_permission_id from dual; insert into general_permissions (permission_id, on_what_id, on_which_table, scope, permission_type) values (v_permission_id, v_on_what_id, v_on_which_table, 'all_users', v_permission_type); return v_permission_id; end grant_permission_to_all_users; procedure revoke_permission ( v_permission_id general_permissions.permission_id%TYPE ) is begin delete from general_permissions where permission_id = v_permission_id; end revoke_permission; function user_permission_id ( v_user_id general_permissions.user_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select permission_id into v_permission_id from general_permissions where on_what_id = v_on_what_id and on_which_table = lower(v_on_which_table) and scope = 'user' and user_id = v_user_id and permission_type = lower(v_permission_type); return v_permission_id; exception when no_data_found then return 0; end user_permission_id; function group_role_permission_id ( v_group_id general_permissions.group_id%TYPE, v_role general_permissions.role%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select permission_id into v_permission_id from general_permissions where on_what_id = v_on_what_id and on_which_table = lower(v_on_which_table) and scope = 'group_role' and group_id = v_group_id and role = v_role and permission_type = lower(v_permission_type); return v_permission_id; exception when no_data_found then return 0; end group_role_permission_id; function group_permission_id ( v_group_id general_permissions.group_id%TYPE, v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select permission_id into v_permission_id from general_permissions where on_what_id = v_on_what_id and on_which_table = lower(v_on_which_table) and scope = 'group' and group_id = v_group_id and permission_type = lower(v_permission_type); return v_permission_id; exception when no_data_found then return 0; end group_permission_id; function reg_users_permission_id ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select permission_id into v_permission_id from general_permissions where on_what_id = v_on_what_id and on_which_table = lower(v_on_which_table) and scope = 'registered_users' and permission_type = lower(v_permission_type); return v_permission_id; exception when no_data_found then return 0; end reg_users_permission_id; function all_users_permission_id ( v_permission_type general_permissions.permission_type%TYPE, v_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE ) return general_permissions.permission_id%TYPE is v_permission_id general_permissions.permission_id%TYPE; begin select permission_id into v_permission_id from general_permissions where on_what_id = v_on_what_id and on_which_table = lower(v_on_which_table) and scope = 'all_users' and permission_type = lower(v_permission_type); return v_permission_id; exception when no_data_found then return 0; end all_users_permission_id; procedure copy_permissions ( v_old_on_what_id general_permissions.on_what_id%TYPE, v_new_on_what_id general_permissions.on_what_id%TYPE, v_on_which_table general_permissions.on_which_table%TYPE, v_user_id1 general_permissions.user_id%TYPE, v_user_id2 general_permissions.user_id%TYPE ) is begin insert into general_permissions (permission_id, on_what_id, on_which_table, scope, user_id, group_id, role, permission_type) select gp_id_sequence.nextval, v_new_on_what_id, lower(v_on_which_table), scope, user_id, group_id, role, permission_type from general_permissions where on_what_id = v_old_on_what_id and on_which_table = lower(v_on_which_table) and (user_id is null or not user_id in (v_user_id1, v_user_id2)); end copy_permissions; end ad_general_permissions; / show errors insert into general_permissions select * from general_permissions_temp; drop table general_permissions_temp; -- END GENERAL-PERMISSIONS -- -- BEGIN BBOARD -- alter table bboard_topics add group_id integer references user_groups; -- END BBOARD -- -- BEGIN ECOMMERCE (EVEANDER 3/4/00) -- alter table ec_products add ( color_list varchar(4000), size_list varchar(4000), style_list varchar(4000) ); alter table ec_items add ( color_choice varchar(4000), size_choice varchar(4000), style_choice varchar(4000) ); alter table ec_creditcards modify ( billing_zip_code varchar(80) ); -- END ECOMMERCE CHANGES -- -- BEGIN SPAM -- alter table spam_history add ( begin_send_time date, finish_send_time date ); alter table daily_spam_files add ( period varchar(64) default 'daily' check (period in ('daily','weekly', 'monthly', 'yearly')) ); -- function to guess an email type, using the default_email_types patterns table CREATE OR REPLACE FUNCTION guess_user_email_type (v_email varchar) RETURN varchar IS cursor mail_cursor is select * from default_email_types; BEGIN FOR mail_val IN mail_cursor LOOP IF upper(v_email) LIKE upper(mail_val.pattern) THEN RETURN mail_val.mail_type; END IF; END LOOP; -- default RETURN 'text/html'; END guess_user_email_type; / show errors create sequence bulkmail_id_sequence start with 1; create table bulkmail_instances ( bulkmail_id integer primary key, description varchar(400), creation_date date not null, creation_user references users(user_id), end_date date, n_sent integer ); create table bulkmail_log ( bulkmail_id references bulkmail_instances, user_id references users, sent_date date not null ); create table bulkmail_bounces ( bulkmail_id references bulkmail_instances, user_id references users, creation_date date default sysdate, active_p char(1) default 't' check(active_p in ('t', 'f')) ); create index bulkmail_user_bounce_idx on bulkmail_bounces(user_id, active_p); -- END SPAM -- -- BEGIN TICKET -- alter table ticket_domains add (message_template varchar(4000)); -- END TICKET -- -- BEGIN NEWS -- create sequence newsgroup_id_sequence start with 4; create table newsgroups ( newsgroup_id integer primary key, -- if scope=all_users, this is the news for all newsgroups -- is scope=registered_users, this is the news for all registered users -- if scope=public, this is the news for the main newsgroup -- if scope=group, this is news associated with a group scope varchar(20) not null, group_id references user_groups, check ((scope='group' and group_id is not null) or (scope='public') or (scope='all_users') or (scope='registered_users')) ); create sequence news_item_id_sequence start with 100000; create table news_items ( news_item_id integer primary key, newsgroup_id references newsgroups not null, title varchar(200) not null, body clob not null, -- is the body in HTML or plain text (the default) html_p char(1) default 'f' check(html_p in ('t','f')), approval_state varchar(15) default 'unexamined' check(approval_state in ('unexamined','approved', 'disapproved')), approval_date date, approval_user references users(user_id), approval_ip_address varchar(50), release_date date not null, expiration_date date not null, creation_date date not null, creation_user not null references users(user_id), creation_ip_address varchar(50) not null ); create index newsgroup_group_idx on newsgroups ( group_id ); create index news_items_idx on news_items ( newsgroup_id ); -- Create the default newsgroups insert into newsgroups (newsgroup_id, scope) values (1, 'registered_users'); insert into newsgroups (newsgroup_id, scope) values (2, 'all_users'); insert into newsgroups (newsgroup_id, scope) values (3, 'public'); -- Create permissions for default newsgroups -- Migration sql commands insert into newsgroups (newsgroup_id, scope, group_id) select newsgroup_id_sequence.nextval, 'group', g.group_id from (select distinct(group_id) from news where group_id is not null) g; -- Insert group news items insert into news_items (news_item_id, newsgroup_id, title, body, html_p, approval_state, release_date, expiration_date, creation_date, creation_user, creation_ip_address) select news_id, ng.newsgroup_id, title, body, html_p, decode(approved_p, 't', 'approved', 'f', 'disapproved', 'unexamined'), release_date, expiration_date, creation_date, creation_user, creation_ip_address from news, newsgroups ng where news.group_id = ng.group_id and news.scope = 'group'; -- Insert public rows insert into news_items (news_item_id, newsgroup_id, title, body, html_p, approval_state, release_date, expiration_date, creation_date, creation_user, creation_ip_address) select news_id, 3, title, body, html_p, decode(approved_p, 't', 'approved', 'f', 'disapproved', 'unexamined'), release_date, expiration_date, creation_date, creation_user, creation_ip_address from news where scope = 'public'; drop index news_idx; drop index news_group_idx; drop table news; drop sequence news_id_sequence; -- migrate the on_which_table, on_what_column in general_comments update general_comments set on_which_table = 'news_items' where on_which_table = 'news'; -- END NEWS -- -- BEGIN CONTEST -- -- don't complain about constraints until we're done set constraints all deferred; -- add domain_id sequence create sequence contest_domain_id_sequence; -- add the domain_id column to contest domains and extra columns alter table contest_domains add (domain_id integer); alter table contest_extra_columns add (domain_id integer); -- populate it declare cursor contest_cursor is select domain from contest_domains; new_domain_id integer; domain_name contest_domains.domain%TYPE; begin open contest_cursor; loop fetch contest_cursor into domain_name; exit when contest_cursor%notfound; select contest_domain_id_sequence.nextval into new_domain_id from dual; update contest_domains set domain_id = new_domain_id where domain = domain_name; update contest_extra_columns set domain_id = new_domain_id where domain = domain_name; end loop; close contest_cursor; end; / show errors; -- turn off primary keyness of domain in contest_domains -- and turn on primary keyness of domain_id in contest_domains alter table contest_domains drop primary key cascade; alter table contest_domains add (primary key(domain_id)); -- turn on uniqueness of domain in contest_domains -- (this also creates an index, which helps when dealing with -- backwards-compatibility when pages use old domain key URLs alter table contest_domains add (unique(domain)); -- set up the references relation from contest_extra_columns alter table contest_extra_columns add constraint contest_xcol_fk foreign key (domain_id) references contest_domains; -- nuke the domain column from contest_extra_columns alter table contest_extra_columns drop column domain; -- add not-nullness to domain_id columns alter table contest_domains modify (domain_id not null); alter table contest_extra_columns modify (domain_id not null); -- and the trick, she is done set constraints all immediate; -- END CONTEST -- -- BEGIN CLASSIFIEDS -- -- The big picture: add new integer primary keys for tables -- that don't have them. The ad_domains table has a -- varchar primary key, so we need to change all the locations -- that refer to ad_domains.domain to refer to ad_domains.domain_id. -- This involves adding a new foreign key column to several tables, -- populating the values, and changing the foregin key constraints -- to refer to the new column. -- drop primary key constraint and all referential -- integrity constraints that refer to 'domain' -- from other tables. We will recreate these constraints -- one by one on the other tables as we add new domain_id -- foreign keys to them. alter table ad_domains drop primary key cascade; -- but 'domain' continues to be restricted to unique values alter table ad_domains add (unique(domain)); -- add new 'domain_id' column, which will be the primary key; -- don't give it a primary key constraint yet, because it has -- no values. alter table ad_domains add ( domain_id integer ); -- add sequence to generate domain_id values create sequence ad_domain_id_seq start with 1; -- populate new domain_id columns update ad_domains set domain_id = ad_domain_id_seq.nextval; commit; -- now add primary key constraint, since the column has values alter table ad_domains add (primary key(domain_id)); -- add new integer primary key and foreign key for domain_id -- (no need to drop primary key constraint since there wasn't one) alter table ad_integrity_checks add ( integrity_check_id integer, domain_id integer ); create sequence ad_integrity_check_id_seq start with 1; -- populate new primary key column update ad_integrity_checks set integrity_check_id = ad_integrity_check_id_seq.nextval; -- and populate foreign key column update ad_integrity_checks set domain_id = (select domain_id from ad_domains where ad_domains.domain = ad_integrity_checks.domain); commit; -- add primary key and foreign key constraints alter table ad_integrity_checks add (primary key(integrity_check_id)); alter table ad_integrity_checks add (foreign key(domain_id) references ad_domains(domain_id)); -- add new integer primary key and foreign key for domain_id -- (no need to drop primary key constraint since there wasn't one) alter table ad_categories add ( category_id integer, domain_id integer ); create sequence ad_category_id_seq start with 1; -- populate new primary key and foreign key columns update ad_categories set category_id = ad_category_id_seq.nextval; update ad_categories set domain_id = (select domain_id from ad_domains where ad_domains.domain = ad_categories.domain); commit; -- add primary key and foreign key constraints for new columns alter table ad_categories add (primary key(category_id)); alter table ad_categories add (foreign key(domain_id) references ad_domains(domain_id)); -- old ad_categories_unique index referred to 'domain' column; -- recreate index with new domain_id column drop index ad_categories_unique; create unique index ad_categories_unique on ad_categories ( domain_id, primary_category ); -- add new domain_id foreign key to replace 'domain' alter table classified_ads add ( domain_id integer ); -- populate foreign key update classified_ads set domain_id = (select domain_id from ad_domains where ad_domains.domain = classified_ads.domain); commit; -- add referential integrity constraint for new foreign key alter table classified_ads add (foreign key(domain_id) references ad_domains(domain_id)); -- and allow old 'domain' column to be null -- (since we can't just drop the column) alter table classified_ads modify (domain null); -- add new domain_id foreign key to replace 'domain' alter table classified_ads_audit add ( domain_id integer ); -- populate new column for old rows update classified_ads_audit set domain_id = (select domain_id from ad_domains where ad_domains.domain = classified_ads_audit.domain); commit; -- replace this view to change 'domain' column to 'domain_id' create or replace view classified_context_view as select ca.classified_ad_id, ca.domain_id, ca.one_line, ca.expires, ca.one_line || ' ' || ca.full_ad || ' ' || u.email || ' ' || u.first_names || ' ' || u.last_name || ' ' || ca.manufacturer || ' ' || ca.model || ' ' as indexed_stuff from classified_ads ca, users u where ca.user_id = u.user_id; -- add new domain_id foreign key to replace 'domain' alter table classified_auction_bids add ( bid_id integer ); create sequence classified_auction_bid_id_seq start with 1; -- populate new bid_id column for old rows update classified_auction_bids set bid_id = classified_auction_bid_id_seq.nextval; commit; -- and add primary key constraint alter table classified_auction_bids add (primary key(bid_id)); -- add new domain_id foreign key to replace 'domain' alter table classified_alerts_last_updates add ( update_id integer ); create sequence classified_alerts_l_u_id_seq start with 1; -- populate new primary key column for old rows update classified_alerts_last_updates set update_id = classified_alerts_l_u_id_seq.nextval; commit; -- and add primary key constraint alter table classified_alerts_last_updates add (primary key(update_id)); -- add new integer primary key and foreign key columns alter table classified_email_alerts add ( alert_id integer, domain_id integer ); create sequence classified_email_alert_id_seq start with 1; -- populate primary key and foreign key columns for old rows update classified_email_alerts set alert_id = classified_email_alert_id_seq.nextval; update classified_email_alerts set domain_id = (select domain_id from ad_domains where ad_domains.domain = classified_email_alerts.domain); commit; -- add in primary key and foreign key constraints alter table classified_email_alerts add (primary key(alert_id)); alter table classified_email_alerts add (foreign key(domain_id) references ad_domains(domain_id)); alter table classified_email_alerts modify (domain null); -- END CLASSIFIEDS UPGRADE ---------------------------------------- -- BEGIN CALENDAR -- -- add extra user_id column to calendar_categories alter table calendar_categories add(user_id references users); alter table calendar_categories drop constraint calendar_category_scope_check; alter table calendar_categories add constraint calendar_category_scope_check check ((scope='group' and group_id is not null) or (scope='user' and user_id is not null) or (scope='public')); alter table calendar_categories drop constraint calendar_category_unique_check; alter table calendar_categories add constraint calendar_category_unique_check unique(scope, category, group_id, user_id); -- END CALENDAR UPGRADE ------------------------------------------- ------------------------------------------------------------ -- SURVEY MODULE is all new ------------------------------------------------------------ @survey-simple ------------------------------------------------------------ -- PULL-DOWN MENUS are all new ------------------------------------------------------------ @pull-down-menus @pull-down-menu-data ----------------------------------------------------------- -- Education module is all new ----------------------------------------------------------- insert into portal_tables (table_id, table_name, adp, admin_url, creation_user, modified_date) values (portal_table_id_sequence.nextval, 'Stock Quotes', '<% set html [DisplayStockQuotes $db]%> <%=$html%>', '', 1, sysdate); insert into portal_tables (table_id, table_name, adp, admin_url, creation_user, modified_date) values (portal_table_id_sequence.nextval,'Current Weather', '<% set html [DisplayWeather $db]%> <%=$html%> ', '', 1, sysdate); insert into portal_tables (table_id, table_name, adp, admin_url,creation_user, modified_date) values (portal_table_id_sequence.nextval,'Classes', '<% set html [GetClassHomepages $db]%> <%=$html%> ', '', 1, sysdate); insert into portal_tables (table_id, table_name, adp, admin_url,creation_user, modified_date) values (portal_table_id_sequence.nextval,'Announcements', '<% set html [GetNewsItems $db]%> <%=$html%>', '', 1, sysdate); insert into portal_tables (table_id, table_name, adp, admin_url,creation_user, modified_date) values (portal_table_id_sequence.nextval,'Calendar', '<% set html [edu_calendar_for_portal $db]%> <%= $html%>', '', 1, sysdate); @education ------------------------------------------------------------- -- Table metadata needed for general permissions ------------------------------------------------------------- @table-metadata