this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: fix album and artist unique constraint case

+121 -20
+29 -1
src/core/types.odin
··· 20 20 mb_id: Maybe(string), // MUSICBRAINZ_ARTISTID, 21 21 } 22 22 23 + delete_artist :: proc(artist: Artist, allocator := context.allocator) { 24 + delete(string(artist.id)) 25 + delete(artist.name) 26 + 27 + if acoust_id, ok := artist.acoust_id.?; ok { 28 + delete(acoust_id) 29 + } 30 + 31 + if mb_id, ok := artist.mb_id.?; ok { 32 + delete(mb_id) 33 + } 34 + } 35 + 36 + 23 37 Album :: struct { 24 38 id: Album_Id, 25 39 title: string, ··· 27 41 mb_rg_id: Maybe(string), // MUSICBRAINZ_RELEASEGROUPID, 28 42 } 29 43 44 + delete_album :: proc(album: Album, allocator := context.allocator) { 45 + delete(string(album.id)) 46 + delete(album.title) 47 + 48 + if mb_id, ok := album.mb_id.?; ok { 49 + delete(mb_id) 50 + } 51 + 52 + if mb_rg_id, ok := album.mb_rg_id.?; ok { 53 + delete(mb_rg_id) 54 + } 55 + } 56 + 57 + 30 58 // Junctions 31 59 ArtistAlbum :: struct { 32 - artist_id: string, 60 + artist_id: Artist_Id, 33 61 album_id: Album_Id, 34 62 } 35 63
+4 -13
src/db/repo/album.odin
··· 182 182 183 183 fmt.printfln("prepared sql: {}\n", sqlite.expanded_sql(stmt)) 184 184 185 - albums := make([dynamic]types.Album, 0, 1) 186 - // defer { 187 - // for album in albums { 188 - // delete(string(album.id)) 189 - // delete(album.title) 190 - // } 191 - // delete_dynamic_array(albums) 192 - // } 185 + album: types.Album 193 186 194 187 for sqlite.step(stmt) == .Row { 195 188 196 - album := types.Album { 189 + album = types.Album { 197 190 id = types.Album_Id(strings.clone_from(sqlite.column_text(stmt, 0))), 198 191 title = strings.clone_from(sqlite.column_text(stmt, 1)), 199 192 } 200 193 201 - append(&albums, album) 202 194 } 203 195 204 - return albums[0], true 196 + return album, true 205 197 } 206 198 207 199 get_album_by_id :: proc( ··· 243 235 albums := make([dynamic]types.Album, 0, 1) 244 236 defer { 245 237 for album in albums { 246 - delete(string(album.id)) 247 - delete(album.title) 238 + types.delete_album(album) 248 239 } 249 240 delete_dynamic_array(albums) 250 241 }
+54 -3
src/db/repo/artist.odin
··· 15 15 artist: types.Artist, 16 16 allocator := context.allocator, 17 17 ) -> ( 18 - new_id: string, 18 + new_id: types.Artist_Id, 19 19 err: db_pkg.DatabaseErrors, 20 20 ) { 21 21 ··· 23 23 ok: bool 24 24 25 25 id := db_pkg.gen_id("artist", allocator) 26 - new_id = id 26 + new_id = types.Artist_Id(id) 27 27 28 28 c_id := strings.clone_to_cstring(id, allocator) 29 29 c_name := strings.clone_to_cstring(artist.name, allocator) ··· 33 33 delete(c_name, allocator) 34 34 } 35 35 36 - query: cstring = "INSERT INTO artist (id, name, mb_id, acoust_id) VALUES (?, ?, ?, ?) ON CONFLICT DO NOTHING" 36 + query: cstring = "INSERT INTO artist (id, name, mb_id, acoust_id) VALUES (?, ?, ?, ?)" 37 37 38 38 stmt: ^sqlite.Statement 39 39 ··· 147 147 148 148 return rc 149 149 } 150 + 151 + 152 + get_artist_by_name :: proc( 153 + db: ^sqlite.Connection, 154 + name: string, 155 + allocator := context.allocator, 156 + ) -> ( 157 + res: types.Artist, 158 + ok: bool, 159 + ) { 160 + 161 + query: cstring = "SELECT * FROM artist WHERE name = ? LIMIT 1" 162 + 163 + stmt: ^sqlite.Statement 164 + 165 + if rc := sqlite.prepare_v2(db, query, c.int(len(query)), &stmt, nil); rc != .Ok { 166 + fmt.eprintfln("failed to prepare statement. result code: {}", rc) 167 + return res, false 168 + } 169 + 170 + defer sqlite.finalize(stmt) 171 + 172 + c_name := strings.clone_to_cstring(name, allocator) 173 + defer delete(c_name) 174 + 175 + if rc := sqlite.bind_text( 176 + stmt, 177 + param_idx = 1, 178 + param_value = c_name, 179 + param_len = c.int(len(name)), 180 + free = {behaviour = .Static}, 181 + ); rc != .Ok { 182 + fmt.eprintfln("failed to bind value to artist name. result code: {}", rc) 183 + return res, false 184 + } 185 + 186 + fmt.printfln("prepared sql: {}\n", sqlite.expanded_sql(stmt)) 187 + 188 + artist: types.Artist 189 + 190 + for sqlite.step(stmt) == .Row { 191 + 192 + artist = types.Artist { 193 + id = types.Artist_Id(strings.clone_from(sqlite.column_text(stmt, 0))), 194 + name = strings.clone_from(sqlite.column_text(stmt, 1)), 195 + } 196 + 197 + } 198 + 199 + return artist, true 200 + }
+1 -1
src/db/repo/junctions.odin
··· 17 17 fmt.printfln("New Artist<->Album $#v", a) 18 18 ok: bool 19 19 20 - c_artist_id := strings.clone_to_cstring(a.artist_id, allocator) 20 + c_artist_id := strings.clone_to_cstring(string(a.artist_id), allocator) 21 21 c_album_id := strings.clone_to_cstring(string(a.album_id), allocator) 22 22 23 23 defer {
+33 -2
src/library/sync.odin
··· 99 99 fmt.printfln("Flac Comment %#v, artist %#v album %#v", flac, artist, album) 100 100 101 101 new_album_id, album_err := db.new_album(db_conn, album) 102 + is_new_album := true 102 103 defer delete(string(new_album_id)) 104 + 103 105 assert(album_err == .None || album_err == .UniqueConstraint) 106 + 104 107 fmt.printfln("\n\nAlbum Err %v", album_err) 105 108 106 109 if (album_err == .UniqueConstraint) { 110 + is_new_album = false 107 111 fmt.printfln("Sync, album unique constraint") 108 112 existing_album, existing_album_ok := db.get_album_by_title(db_conn, album.title) 113 + 109 114 assert(existing_album_ok) 115 + 116 + defer types.delete_album(existing_album) 117 + 110 118 fmt.printfln("Existing Album %v", existing_album) 119 + 120 + delete(string(new_album_id)) 111 121 new_album_id = types.Album_Id(strings.clone(string(existing_album.id))) 112 122 } 113 123 ··· 115 125 fmt.printfln("New album |%v| with id |%v|", album.title, new_album_id) 116 126 117 127 new_artist_id, artist_err := db.new_artist(db_conn, artist) 118 - defer delete(new_artist_id) 128 + 129 + is_new_artist := true 130 + 131 + defer delete(string(new_artist_id)) 119 132 assert(artist_err == .None || artist_err == .UniqueConstraint) 133 + 120 134 fmt.printfln("New artist |%v| with id |%v|", artist.name, new_artist_id) 121 135 122 - if (flac.album_artist == artist.name) { 136 + if (artist_err == .UniqueConstraint) { 137 + is_new_artist = false 138 + 139 + fmt.printfln("Sync, artist unique constraint") 140 + existing_artist, existing_artist_ok := db.get_artist_by_name(db_conn, artist.name) 141 + 142 + assert(existing_artist_ok) 143 + 144 + defer types.delete_artist(existing_artist) 145 + 146 + fmt.printfln("Existing artist %v", existing_artist) 147 + 148 + delete(string(new_artist_id)) 149 + new_artist_id = types.Artist_Id(strings.clone(string(existing_artist.id))) 150 + } 151 + 152 + 153 + if (flac.album_artist == artist.name && (is_new_artist || is_new_album)) { 123 154 artist_album := types.ArtistAlbum { 124 155 album_id = new_album_id, 125 156 artist_id = new_artist_id,