package shakuhachi
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A music collection manager
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.2.0.tar.gz
sha256=966fc8667c2aa9830e64950d2de74bd564a65d60e1f50cfd3dc1e99ef106dc47
sha512=6423ce04d784ba521a7f49fabdafbe036e2dd80cd08ca999fdc6767262d7f12aa4e5002d65efd4c568b343eaabf4d680191c88334d629e1ca0156084531e9e0b
doc/src/shakuhachi.database/albumParticipant.ml.html
Source file albumParticipant.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139(*****************************************************************************) (* *) (* Copyright (C) 2026 Yves Ndiaye *) (* *) (* This Source Code Form is subject to the terms of the Mozilla Public *) (* License, v. 2.0. If a copy of the MPL was not distributed with this *) (* file, You can obtain one at https://mozilla.org/MPL/2.0/. *) (* *) (*****************************************************************************) type t = { album_id : Int64.t; artist_id : Int64.t; role : Role.t } let table_name = "album_participants" let foreign_album_id = "album_id" let foreign_artist_id = "artist_id" let key_role = "role" let p_album_id = Printf.sprintf "%s.%s" table_name foreign_album_id let p_artist_id = Printf.sprintf "%s.%s" table_name foreign_artist_id let p_role = Printf.sprintf "%s.%s" table_name key_role let sql_table = Printf.sprintf {|CREATE TABLE IF NOT EXISTS %s ( %s INTEGER NOT NULL, %s INTEGER NOT NULL, %s INTEGER, UNIQUE (%s, %s, %s), FOREIGN KEY (%s) REFERENCES %s (%s) ON UPDATE CASCADE ON DELETE CASCADE FOREIGN KEY (%s) REFERENCES %s (%s) ON UPDATE CASCADE ON DELETE CASCADE );|} table_name foreign_album_id foreign_artist_id key_role foreign_album_id foreign_artist_id key_role foreign_album_id Album.table_name Album.primary_key foreign_artist_id Artist.table_name Artist.primary_key let init ~album_id ~artist_id role = { album_id; artist_id; role } let update_artist database old new' = let ( let* ) rc f = match rc with | Sqlite3.Rc.OK | Sqlite3.Rc.DONE -> f () | rc -> let message = Sqlite3.errmsg database in Error (rc, message) in let statement = Printf.sprintf "UPDATE %s SET %s = ?1 WHERE %s = ?2;" table_name foreign_artist_id foreign_artist_id in let statement = Sqlite3.prepare database statement in let* () = Sqlite3.bind_int64 statement 1 new' in let* () = Sqlite3.bind_int64 statement 2 old in match Sqlite3.step statement with | Sqlite3.Rc.OK | Sqlite3.Rc.DONE | Sqlite3.Rc.CONSTRAINT -> let* () = Sqlite3.finalize statement in Ok () | rc -> let message = Sqlite3.errmsg database in Error (rc, message) let insert database t = let { album_id; artist_id; role } = t in let statement' = Printf.sprintf "INSERT INTO %s (album_id, artist_id, role) VALUES (?, ?, ?);" table_name in let ( let* ) rc f = match rc with | Sqlite3.Rc.OK | Sqlite3.Rc.DONE -> f () | rc -> let message = Sqlite3.errmsg database in Error (rc, message) in let statement = Sqlite3.prepare database statement' in let* () = Sqlite3.bind_int64 statement 1 album_id in let* () = Sqlite3.bind_int64 statement 2 artist_id in let* () = Sqlite3.bind_int statement 3 (Role.to_int role) in match Sqlite3.step statement with | Sqlite3.Rc.OK | Sqlite3.Rc.DONE | Sqlite3.Rc.CONSTRAINT -> let* () = Sqlite3.finalize statement in Ok () | rc -> let message = Sqlite3.errmsg database in Error (rc, message) (** [find_or_insert ~compilation database artists album] tries to find an album in [database] with the name [album.name] and at least an arist with the name is in [artists] unless [compilation], in this case only the [album.name] is check to discriminate albums *) let find_or_insert ~compilation database (artists : (Artist.t * Role.t) list) (album : Album.t) = let module Albums = Set.Make (struct type t = Album.t let compare (lhs : Album.t) (rhs : Album.t) = compare lhs.id rhs.id end) in let ( let* ) = Result.bind in let query = Printf.sprintf "SELECT %s.*, %s FROM %s INNER JOIN %s ON %s = %s INNER JOIN %s ON %s = \ %s;" Album.table_name Artist.p_name table_name Album.table_name p_album_id Album.p_id Artist.table_name p_artist_id Artist.p_id in let statement = Sqlite3.prepare database query in let _rc, albums = Sqlite3.fold statement ~init:Albums.empty ~f:(fun albums _ -> let qalbum, offset = Album.columns statement 0 in let artist_name = Sqlite3.column_text statement offset in let artists () = compilation || List.exists (fun ((artist : Artist.t), _) -> artist.name = artist_name) artists in let matched = qalbum.name = album.name && artists () in match matched with true -> Albums.add qalbum albums | false -> albums ) in match Albums.min_elt_opt albums with | None -> let* qalbum = Album.insert database album in let () = List.iter (fun ((artist : Artist.t), role) -> let t = { album_id = qalbum.id; artist_id = artist.id; role } in match insert database t with Ok () -> () | Error _e -> () ) artists in Ok qalbum | Some qalbum -> Ok qalbum (* Test *) let equal : t -> t -> bool = ( = ) let compare : t -> t -> int = Stdlib.compare
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>