From 729bf7a6534d0fd6948b505681f75c182c6b54be Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Sun, 9 Jul 2017 23:09:37 -0700 Subject: [PATCH] Implemented writing songs to playlist --- .../201707091522_playlists_tables/up.sql | 1 - src/db/schema.sqlite | Bin 69632 -> 69632 bytes src/playlist.rs | 197 +++++++++++++++--- 3 files changed, 170 insertions(+), 28 deletions(-) diff --git a/src/db/migrations/201707091522_playlists_tables/up.sql b/src/db/migrations/201707091522_playlists_tables/up.sql index 7f886cb..69dea8f 100644 --- a/src/db/migrations/201707091522_playlists_tables/up.sql +++ b/src/db/migrations/201707091522_playlists_tables/up.sql @@ -11,7 +11,6 @@ CREATE TABLE playlist_songs ( playlist INTEGER NOT NULL, path TEXT NOT NULL, ordering INTEGER NOT NULL, - FOREIGN KEY(path) REFERENCES songs(path), FOREIGN KEY(playlist) REFERENCES playlists(id) ON DELETE CASCADE ON UPDATE CASCADE, UNIQUE(playlist, ordering) ON CONFLICT REPLACE ); diff --git a/src/db/schema.sqlite b/src/db/schema.sqlite index 84aa6e454b1627399e1f85303fca1c9b19234094..7273458004d2865e5ca994d9835cbb271e1f82d9 100644 GIT binary patch delta 523 zcmZvVJ!lj`6vubHyIC)0nFNF*AF$_P;G&6{eKR{BDU_Mp*(O1QVkcObC?ZHOXKjpE zh^ELfRwiJq>_l!6><%n#w6Y48evrZ$KXrqOL+Vr&F(e7#GqkD$v$@-Pc_3KNib~$Rg zt6|N3Ll>*#hL*k_5D9q72l zXzbKrUX8}C4dg~?&=G?=#?d%&)JX_{Jf`FJ{{PdfmzR)_`yTG+qvSnaxa1=*npv#2 zSJv7$AFi!DSfD@Oy*9qqZ;j|`ax?=XJ|?3&Ib;Yx zh>c(owner: &str, db: &T) -> Result> @@ -38,41 +55,138 @@ fn list_playlists(owner: &str, db: &T) -> Result> let connection = connection.lock().unwrap(); let connection = connection.deref(); - let user : User; + let user: User; { - use self::users::dsl::*; - user = users.filter(name.eq(owner)).select((id, name)).first(connection)?; + use self::users::dsl::*; + user = users + .filter(name.eq(owner)) + .select((id, name)) + .first(connection)?; } - + { use self::playlists::dsl::*; - let found_playlists : Vec = Playlist::belonging_to(&user).select(name).load(connection)?; + let found_playlists: Vec = Playlist::belonging_to(&user) + .select(name) + .load(connection)?; Ok(found_playlists) } } -fn save_playlist(name: &str, owner: &str, content: &Vec, db: &T) -> Result<()> +fn save_playlist(name: &str, owner: &str, content: &Vec, db: &T) -> Result<()> where T: ConnectionSource + VFSSource { - let connection = db.get_connection(); - let connection = connection.lock().unwrap(); - let connection = connection.deref(); + // TODO transaction for content delete+add + let user: User; + let new_playlist: NewPlaylist; + let playlist: Playlist; - let new_playlist = NewPlaylist { - name: name.into(), - owner: users::table - .filter(users::columns::name.eq(owner)) - .select(users::columns::id) - .get_result(connection)?, - }; + { + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); - diesel::insert(&new_playlist) + // Find owner + { + use self::users::dsl::*; + user = users + .filter(name.eq(owner)) + .select((id, name)) + .get_result(connection)?; + } + + // Create playlist + new_playlist = NewPlaylist { + name: name.into(), + owner: user.id, + }; + + diesel::insert(&new_playlist) .into(playlists::table) .execute(connection)?; + { + use self::playlists::dsl::*; + playlist = playlists + .filter(name.eq(name).and(owner.eq(user.id))) + .get_result(connection)?; + } + + // Delete old content (if any) + let old_songs = PlaylistSong::belonging_to(&playlist); + diesel::delete(old_songs).execute(connection)?; + } + + // Insert content + let vfs = db.get_vfs()?; + let mut new_songs: Vec = Vec::new(); + new_songs.reserve(content.len()); + for (i, path) in content.iter().enumerate() { + let virtual_path = Path::new(&path); + if let Some(real_path) = vfs.virtual_to_real(virtual_path) + .ok() + .and_then(|p| p.to_str().map(|s| s.to_owned())) { + new_songs.push(NewPlaylistSong { + playlist: playlist.id, + path: real_path.into(), + ordering: i as i32, + }); + } + } + + { + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); + + diesel::insert(&new_songs) + .into(playlist_songs::table) + .execute(connection)?; + } + Ok(()) } +fn read_playlist(playlist_name: &str, owner: &str, db: &T) -> Result> + where T: ConnectionSource + VFSSource +{ + let user: User; + let playlist: Playlist; + let playlist_songs: Vec; + let vfs = db.get_vfs()?; + + { + let connection = db.get_connection(); + let connection = connection.lock().unwrap(); + let connection = connection.deref(); + + // Find owner + { + use self::users::dsl::*; + user = users + .filter(name.eq(owner)) + .select((id, name)) + .get_result(connection)?; + } + + // Find playlist + { + use self::playlists::dsl::*; + playlist = playlists + .filter(name.eq(playlist_name).and(owner.eq(user.id))) + .get_result(connection)?; + } + + // Find content + playlist_songs = PlaylistSong::belonging_to(&playlist) + .order(playlist_songs::columns::ordering) + .get_results(connection)?; + } + + // TODO + Ok(Vec::new()) +} + fn delete_playlist(playlist_name: &str, owner: &str, db: &T) -> Result<()> where T: ConnectionSource + VFSSource { @@ -80,29 +194,32 @@ fn delete_playlist(playlist_name: &str, owner: &str, db: &T) -> Result<()> let connection = connection.lock().unwrap(); let connection = connection.deref(); - let user : User; + let user: User; { - use self::users::dsl::*; - user = users.filter(name.eq(owner)).select((id, name)).first(connection)?; + use self::users::dsl::*; + user = users + .filter(name.eq(owner)) + .select((id, name)) + .first(connection)?; } - + { use self::playlists::dsl::*; let q = Playlist::belonging_to(&user).filter(name.eq(playlist_name)); diesel::delete(q).execute(connection)?; } + Ok(()) } #[test] fn test_create_playlist() { let db = db::_get_test_db("create_playlist.sqlite"); - let playlist_content = Vec::new(); let found_playlists = list_playlists("test_user", &db).unwrap(); assert!(found_playlists.is_empty()); - save_playlist("chill_and_grill", "test_user", &playlist_content, &db).unwrap(); + save_playlist("chill_and_grill", "test_user", &Vec::new(), &db).unwrap(); let found_playlists = list_playlists("test_user", &db).unwrap(); assert_eq!(found_playlists.len(), 1); assert_eq!(found_playlists[0], "chill_and_grill"); @@ -129,3 +246,29 @@ fn test_delete_playlist() { let delete_result = delete_playlist("mellow_bungalow", "someone_else", &db); assert!(delete_result.is_err()); } + +#[test] +fn test_fill_playlist() { + use index; + + let db = db::_get_test_db("fill_playlist.sqlite"); + index::update(&db).unwrap(); + + let mut playlist_content: Vec = index::flatten(&db, Path::new("root")) + .unwrap() + .into_iter() + .map(|s| s.path) + .collect(); + assert_eq!(playlist_content.len(), 12); + + let first_song = playlist_content[0].clone(); + playlist_content.push(first_song); + assert_eq!(playlist_content.len(), 13); + + save_playlist("all_the_music", "test_user", &playlist_content, &db).unwrap(); + + // let songs = read_playlist("all_the_music", "test_user", &db).unwrap(); + // assert_eq!(songs.len(), 13); + // assert_eq!(songs[0].title, Some("Above The Water".to_owned())); + // assert_eq!(songs[12].title, Some("Above The Water".to_owned())); +}