-- @author tigre@ybos.net -- @author jennie@ybos.net -- openacs port: Ola Hansson rockola@mail.com create function inline_0 () returns integer as ' begin PERFORM acs_object_type__create_type ( ''mp3'', -- object_type ''MP3'', -- pretty_name ''MP3s'', -- pretty_plural ''acs_object'', -- supertype ''MP3_MP3S'', -- table_name ''MP3_ID'', -- id_column null, -- package_name ''f'', -- abstract_p null, -- type_extension_table null -- name_method ); PERFORM acs_object_type__create_type ( ''mp3_playlist'', -- object_type ''Playlist'', -- pretty_name ''Playlists'', -- pretty_plural ''acs_object'', -- supertype ''MP3_PLAYLISTS'', -- table_name ''PLAYLIST_ID'', -- id_column null, -- package_name ''f'', -- abstract_p null, -- type_extension_table null -- name_method ); return 0; end;' language 'plpgsql'; select inline_0 (); drop function inline_0 (); create table mp3_mp3s ( mp3_id integer constraint mp3_mp3_id_fk references acs_objects (object_id) constraint mp3_mp3s_pk primary key, file_path varchar(200) constraint mp3_mp3s_nn not null constraint mp3_mp3s_file_unique unique, title varchar(200) constraint mp3_mp3s_title_nn not null, artist varchar(100), bitrate varchar(50), album varchar(200), tracknum integer, genre varchar(100), year varchar(10), layer integer, copyright_p boolean default 'f' constraint mp3_mp3s_copyright_p_ck check(copyright_p in ('t','f')), version integer, mode_num integer, stereo_p boolean default 'f' constraint mp3_mp3s_stereo_p_ck check(stereo_p in ('t','f')), frequency numeric, minutes integer, seconds integer, comments varchar(200), vbr_p boolean default 'f' constraint mp3_mp3s_vbr_p_ck check(vbr_p in ('t','f')), state varchar(50), deleted_p boolean default 'f' constraint mp3_mp3s_deleted_p_ck check(deleted_p in ('t','f')) ); create table mp3_playlists ( playlist_id integer constraint mp3_playlist_id_fk references acs_objects (object_id) constraint mp3_playlists_pk primary key, name varchar(100), shuffle_p boolean default 'f' constraint mp3_playlists_shuffle_p_ck check(shuffle_p in ('f','t')), remove_threshold integer ); create table mp3_mp3_playlist_map ( mp3_id integer constraint mp3_map_mp3_id_fk references mp3_mp3s (mp3_id), playlist_id integer constraint mp3_map_playlist_id_fk references mp3_playlists (playlist_id), sort_key integer, -- This pk constraint will have ot be changed, maybe add a column -- for the pk, thus allowing multiple instances of a given song -- on a playlist constraint mp3_map_pk primary key (mp3_id,playlist_id) ); create table mp3_mp3_stats ( mp3_id integer constraint mp3_mp3_stats_mp3_id_fk references mp3_mp3s (mp3_id), user_id integer constraint mp3_mp3_stats_user_id_fk references users(user_id), access_date timestamptz constraint mp3_mp3_stats_access_date_nn not null ); create table mp3_playlist_stats ( playlist_id integer constraint mp3_playlist_stats_playlist_fk references mp3_playlists (playlist_id), user_id integer constraint mp3_playlists_stats_user_id_fk references users(user_id), access_date timestamptz constraint mp3_playlist_stats_date_nn not null ); create table mp3_votes ( mp3_id integer constraint mp3_votes_mp3_id_fk references mp3_mp3s (mp3_id), playlist_id integer constraint mp3_votes_playlist_id_fk references mp3_playlists (playlist_id), user_id integer constraint mp3_votes_user_id_fk references users(user_id), vote integer constraint mp3_votes_vote_nn not null, vote_date timestamptz ); create view mp3_mp3_playlist_map_view as select m.mp3_id, m.playlist_id, m.sort_key, coalesce(v.total,0) as total from mp3_mp3_playlist_map m left join (select mp3_id, playlist_id, sum(vote) as total from mp3_votes group by mp3_id, playlist_id) v using (mp3_id, playlist_id); create view mp3_mp3s_not_deleted as select * from mp3_mp3s where deleted_p = 'f'; create view mp3_playlist_song_count as select mpv.playlist_id, count(*) as songs from mp3_mp3_playlist_map_view mpv, mp3_mp3s_not_deleted mnd, mp3_playlists mp where mpv.mp3_id = mnd.mp3_id and mpv.playlist_id = mp.playlist_id and mpv.total > mp.remove_threshold group by mpv.playlist_id; create function mp3__new (integer,varchar,varchar) returns integer as ' declare p_mp3_id alias for $1; -- default null p_file_path alias for $2; -- default null p_title alias for $3; -- default null p_deleted_p boolean default ''f''; p_object_type varchar default ''mp3''; p_creation_date timestamptz default current_timestamp; p_creation_user integer default null; p_creation_ip varchar default null; p_context_id integer default null; v_mp3_id mp3_mp3s.mp3_id%TYPE; begin v_mp3_id := acs_object__new ( p_mp3_id, -- object_id p_object_type, -- object_type p_creation_date, -- creation_date p_creation_user, -- creation_user p_creation_ip, -- creation_ip p_context_id -- context_id ); insert into mp3_mp3s (mp3_id, file_path, title, deleted_p) values (v_mp3_id, p_file_path, p_title, p_deleted_p); return v_mp3_id; end;' language 'plpgsql'; create function mp3__delete (integer) returns integer as ' declare p_mp3_id alias for $1; begin delete from mp3_mp3s where mp3_id = p_mp3_id; raise NOTICE ''Deleting mp3...''; PERFORM acs_object__delete(p_mp3_id); return 0; end;' language 'plpgsql'; create function mp3__mark_as_deleted (integer) returns integer as ' declare p_mp3_id alias for $1; begin update mp3_mp3s set deleted_p =''t'' where mp3_id = p_mp3_id; return 0; end;' language 'plpgsql'; create function mp3_playlist__new (integer,varchar,boolean,integer,varchar,timestamptz,integer,varchar,integer) returns integer as ' declare p_playlist_id alias for $1; -- default null p_name alias for $2; -- default null p_shuffle_p alias for $3; -- default ''f'' p_remove_threshold alias for $4; -- default null p_object_type alias for $5; -- default ''mp3_playlist'' p_creation_date alias for $6; -- default now() p_creation_user alias for $7; -- default null p_creation_ip alias for $8; -- default null p_context_id alias for $9; v_playlist_id acs_objects.object_id%TYPE; begin v_playlist_id := acs_object__new ( p_playlist_id, -- object_id p_object_type, -- object_type p_creation_date, -- creation_date p_creation_user, -- creation_user p_creation_ip, -- creation_ip p_context_id -- context_id ); insert into mp3_playlists (playlist_id, name, shuffle_p, remove_threshold) values (v_playlist_id, p_name, p_shuffle_p, p_remove_threshold); return v_playlist_id; end;' language 'plpgsql'; create function mp3_playlist__delete (integer) returns integer as ' declare p_playlist_id alias for $1; begin delete from mp3_votes where playlist_id = p_playlist_id; delete from mp3_mp3_playlist_map where playlist_id = p_playlist_id; delete from mp3_playlists where playlist_id = p_playlist_id; raise NOTICE ''Deleting playlist...''; PERFORM acs_object__delete(p_playlist_id); return 0; end;' language 'plpgsql'; -- Note: item_add uses "insert after" ordering, so "order" points to -- the last record _not_ to be updated create function mp3_playlist__item_add (integer,integer,integer) returns integer as ' declare p_mp3_id alias for $1; p_playlist_id alias for $2; p_sort_key alias for $3; -- default null v_map_cur RECORD; -- Generic record used in for loop v_l_sort_key mp3_mp3_playlist_map.sort_key%TYPE; v_l_max_sort_key mp3_mp3_playlist_map.sort_key%TYPE; v_l_new_sort_key mp3_mp3_playlist_map.sort_key%TYPE; begin select coalesce(max(sort_key),0) into v_l_max_sort_key from mp3_mp3_playlist_map where playlist_id = p_playlist_id; if p_sort_key > v_l_max_sort_key then v_l_sort_key := v_l_max_sort_key; else v_l_sort_key := p_sort_key; end if; v_l_new_sort_key := v_l_sort_key + 2; FOR v_map_cur IN select mmpm.mp3_id, mmpm.playlist_id, mmpm.sort_key from mp3_mp3_playlist_map mmpm, mp3_mp3s_not_deleted mmnd where mmpm.mp3_id = mmnd.mp3_id and mmpm.playlist_id = p_playlist_id and mmpm.sort_key > p_sort_key order by mmpm.sort_key LOOP update mp3_mp3_playlist_map set sort_key = v_l_new_sort_key where mp3_id = v_map_cur.mp3_id and playlist_id = v_map_cur.playlist_id; v_l_new_sort_key := v_l_new_sort_key + 1; END LOOP; insert into mp3_mp3_playlist_map (mp3_id, playlist_id, sort_key) values (p_mp3_id, p_playlist_id, v_l_sort_key + 1); return 0; end;' language 'plpgsql'; -- We'll just delete the mapping and it's corresponding votes -- We won't worry about gaps in the order create function mp3_playlist__item_remove (integer,integer) returns integer as ' declare p_mp3_id alias for $1; p_playlist_id alias for $2; begin delete from mp3_votes where mp3_id = p_mp3_id and playlist_id = p_playlist_id; delete from mp3_mp3_playlist_map where mp3_id = p_mp3_id and playlist_id = p_playlist_id; return 0; end;' language 'plpgsql'; create function mp3_playlist__vote_cast (integer,integer,integer,integer,timestamptz) returns integer as ' declare p_user_id alias for $1; p_playlist_id alias for $2; p_mp3_id alias for $3; p_vote alias for $4; p_vote_date alias for $5; -- default now() v_l_vote_sum mp3_votes.vote%TYPE; begin insert into mp3_votes (mp3_id, playlist_id, user_id, vote, vote_date) values (p_mp3_id, p_playlist_id, p_user_id, p_vote, p_vote_date); select total into v_l_vote_sum from mp3_mp3_playlist_map_view where mp3_id = p_mp3_id and playlist_id = p_playlist_id; return v_l_vote_sum; end;' language 'plpgsql'; -- "swap w/ next" create function mp3_playlist__item_order_swap (integer,integer) returns integer as ' declare p_playlist_id alias for $1; p_sort_key alias for $2; v_l_next_order mp3_mp3_playlist_map.sort_key%TYPE; begin select min(sort_key) into v_l_next_order from mp3_mp3_playlist_map m, mp3_mp3s_not_deleted d where m.mp3_id = d.mp3_id and m.sort_key > p_sort_key; update mp3_mp3_playlist_map set sort_key = (case when sort_key = p_sort_key then p_sort_key + 1 else p_sort_key end) where sort_key in (p_sort_key,v_l_next_order); return 0; end;' language 'plpgsql';