-- -- Classified Ads data-model.sql -- -- Created July 12, 1996 by Philip Greenspun (philg@mit.edu) -- -- added auction stuff on December 21, 1996 -- -- converted from Illustra to Oracle January 5, 1998 -- -- edited to run from generic community system users table -- (instead of email address/name stored in row) teadams@mit.eud April 2, 1998 -- edited by philg on 11/18/98 to incorporate employment ad fields -- and also domain_type -- edited by teadams@mit.edu on 1/7/98 to add active_p to ad_domains -- edited by teadams@mit.edu on 2/10/98 to prevent multiple seed inserts into -- classified_alerts_last_updates -- edited by curtisg@arsdigita.com on 3/9/00 to convert primary keys -- to integers create table ad_domains ( domain_id integer primary key, -- short key, e.g., "Jobs" domain varchar(30) unique, -- a description for this domain, e.g., "Jobs classifieds" -- or "Job Listings", this is designed to serve as a -- hypertext anchor back to the top-level page full_noun varchar(100), primary_maintainer_id integer not null references users(user_id), domain_type varchar(30), -- e.g., 'employment', 'automotive' blurb varchar(4000), blurb_bottom varchar(4000), insert_form_fragments varchar(4000), ad_deletion_blurb varchar(4000), default_expiration_days integer default 100, levels_of_categorization integer default 1, user_extensible_cats_p char(1) default 'f' check(user_extensible_cats_p in ('t','f')), wtb_common_p char(1) default 'f' check(wtb_common_p in ('t','f')), auction_p char(1) default 'f' check(auction_p in ('t','f')), geocentric_p char(1) default 'f' check(geocentric_p in ('t','f')), --should this show up on the user interface? active_p char(1) default 't' check (active_p in ('t','f')) ); create sequence ad_domain_id_seq start with 1; -- we test these on inserts or updates to the table -- with user interface complaints --- check_code is something that goes into a Tcl If statement create table ad_integrity_checks ( integrity_check_id integer primary key, domain_id integer references ad_domains(domain_id), check_code varchar(4000), error_message varchar(4000) ); create sequence ad_integrity_check_id_seq start with 1; -- -- We have a lot of redundant info in this -- (e.g., each primary_category may be represented 50 times) -- but we query into this with DISTINCT and we memo-ize -- so we don't care -- -- the entire user interface is built from this -- create table ad_categories ( category_id integer primary key, domain_id integer references ad_domains(domain_id), primary_category varchar(100), subcategory_1 varchar(100), subcategory_2 varchar(100), ad_placement_blurb varchar(4000) ); create sequence ad_category_id_seq start with 1; -- if we're going to have a system where we only use primary -- category then presumably these should be constrained unique -- we can do that with an index: create unique index ad_categories_unique on ad_categories ( domain_id, primary_category ); -- old system had about 10,000 ads so far, this way we'll know whether -- or not an ad was inserted under the Oracle regime create sequence classified_ad_id_sequence start with 200000; create table classified_ads ( classified_ad_id integer primary key, user_id integer not null references users, domain_id integer not null references ad_domains(domain_id), originating_ip varchar(16), -- stored as string, separated by periods posted date not null, expires date, wanted_p char(1) default 'f' check(wanted_p in ('t','f')), private_p char(1) default 't' check(private_p in ('t','f')), -- if 'f', the reply_to link will not be displayed with the ad reply_to_poster_p char(1) default 't' check(reply_to_poster_p in ('t','f')), primary_category varchar(100), subcategory_1 varchar(100), subcategory_2 varchar(100), manufacturer varchar(50), model varchar(50), date_produced date, item_size varchar(100), color varchar(50), location varchar(200), us_citizen_p char(1) default 'f' check(us_citizen_p in ('t','f')), one_line varchar(150), full_ad varchar(3600), -- is the ad in HTML or plain text (the default) html_p char(1) default 'f' check(html_p in ('t','f')), graphic_url varchar(200), price number(9,2), currency varchar(50) default 'US dollars', auction_p char(1) default 't' check(auction_p in ('t','f')), country varchar(2), state varchar(30), -- when system is used for employment ads (Cognet wanted these) employer varchar(100), salary_range varchar(200), last_modified date ); create or replace trigger classified_update_last_mod before insert or update on classified_ads for each row begin :new.last_modified :=SYSDATE; IF inserting and :new.posted is null THEN :new.posted := SYSDATE; END IF; end classified_update_last_mod; / show errors create index classified_ads_by_primary_cat on classified_ads (primary_category); create index classified_ads_by_subcat_1 on classified_ads (subcategory_1); -- for the "remember to update your ads spam" create index classified_ads_by_email on classified_ads (user_id); -- the auction system create table classified_auction_bids ( bid_id integer primary key, classified_ad_id not null references classified_ads, user_id not null references users, bid number(9,2), currency varchar(100) default 'US dollars', bid_time date, location varchar(100) ); create sequence classified_auction_bid_id_seq start with 1; create index classified_auction_bids_index on classified_auction_bids (classified_ad_id); -- audit table (we hold deletions, big changes, here) -- warning: this gives SQL*Plus heartburn if typed at the shell create table classified_ads_audit ( classified_ad_id integer, user_id integer, domain_id integer, originating_ip varchar(16), posted date, expires date, wanted_p char(1), private_p char(1), reply_to_poster_p char(1), primary_category varchar(100), subcategory_1 varchar(100), subcategory_2 varchar(100), manufacturer varchar(50), model varchar(50), date_produced date, item_size varchar(100), color varchar(50), location varchar(200), us_citizen_p char(1), one_line varchar(150), full_ad varchar(3600), html_p char(1), graphic_url varchar(200), price number(9,2), currency varchar(50), auction_p char(1), country varchar(2), state varchar(30), employer varchar(100), salary_range varchar(200), last_modified date, -- from where user edited ad audit_ip varchar(16), -- deleted by moderator? deleted_by_admin_p char(1) default 'f' check(deleted_by_admin_p in ('t','f')) ); create index classified_ads_audit_idx on classified_ads_audit(classified_ad_id); create index classified_ads_audit_user_idx on classified_ads_audit(user_id); -- ConText index stuff -- this is also good for sequential scanning with pseudo_contains 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; -- email alert system -- -- this holds the last time we sent out notices -- create table classified_alerts_last_updates ( update_id integer primary key, weekly date, weekly_total integer, daily date, daily_total integer, monthu date, monthu_total integer ); declare n_last_update_seed_rows integer; begin select count(*) into n_last_update_seed_rows from classified_alerts_last_updates where weekly = 'sydate' and daily = 'sysdate' and monthu = 'sysdate'; if n_last_update_seed_rows = 0 then insert into classified_alerts_last_updates (update_id, weekly, weekly_total, daily, daily_total, monthu, monthu_total) values (1, sysdate,0,sysdate,0,sysdate,0); end if; end; / create table classified_email_alerts ( alert_id integer primary key, domain_id not null references ad_domains(domain_id), user_id not null references users, valid_p char(1) default 't' check(valid_p in ('t','f')), expires date, howmuch varchar(100), -- 'everything', 'one_line' frequency varchar(100), -- 'instant', 'daily', 'Monday/Thursday', 'weekly', etc. alert_type varchar(20), -- 'all', 'category', 'keywords' category varchar(100), keywords varchar(100), established date ); create sequence classified_email_alert_id_seq start with 1; create or replace trigger classified_ea_established before insert on classified_email_alerts for each row when (new.established is null) begin :new.established :=SYSDATE; end; / show errors