feat(db): cascade-cleanup queries for M7 #372 track removal
DeleteTrack returns album_id + artist_id so the calling service can chain the album-empty / artist-empty cascade. DeleteAlbumIfEmpty and DeleteArtistIfEmpty are no-ops when other rows still reference the parent — the service treats pgx.ErrNoRows as "not orphaned, skip".
This commit is contained in:
@@ -47,6 +47,30 @@ func (q *Queries) CountAlbumsMatching(ctx context.Context, dollar_1 string) (int
|
||||
return count, err
|
||||
}
|
||||
|
||||
const deleteAlbumIfEmpty = `-- name: DeleteAlbumIfEmpty :one
|
||||
DELETE FROM albums a
|
||||
WHERE a.id = $1
|
||||
AND NOT EXISTS (SELECT 1 FROM tracks t WHERE t.album_id = a.id)
|
||||
RETURNING a.id, a.artist_id
|
||||
`
|
||||
|
||||
type DeleteAlbumIfEmptyRow struct {
|
||||
ID pgtype.UUID
|
||||
ArtistID pgtype.UUID
|
||||
}
|
||||
|
||||
// M7 #372: deletes the album row only when it has no remaining tracks.
|
||||
// Used after a track delete to tidy up orphaned albums. RETURNING gives
|
||||
// us the artist_id so the service can chain into the artist-empty check.
|
||||
// Returns no rows when the album still has tracks; the service treats
|
||||
// pgx.ErrNoRows as "album not orphaned, skip cascade".
|
||||
func (q *Queries) DeleteAlbumIfEmpty(ctx context.Context, id pgtype.UUID) (DeleteAlbumIfEmptyRow, error) {
|
||||
row := q.db.QueryRow(ctx, deleteAlbumIfEmpty, id)
|
||||
var i DeleteAlbumIfEmptyRow
|
||||
err := row.Scan(&i.ID, &i.ArtistID)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getAlbumByArtistAndTitle = `-- name: GetAlbumByArtistAndTitle :one
|
||||
SELECT id, title, sort_title, artist_id, release_date, mbid, cover_art_path, created_at, updated_at FROM albums WHERE artist_id = $1 AND title = $2 LIMIT 1
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user