fix: preserve album track order for NULL discNumber (nulls first)

Prisma's default ASC sort uses Postgres NULLS LAST, so the compound
order `[discNumber asc, trackNo asc]` added in PR #170 reorders
tracks in mixed-state libraries: any album where some tracks have
been rescanned post-migration (getting discNumber) and others have
not (staying NULL) ends up with the numbered-disc tracks first and
the NULL-disc tracks dumped at the end, breaking the original
trackNo order that users expected.

Fix: use `{ sort: 'asc', nulls: 'first' }` on discNumber in all six
orderBy call sites (library/albums, offline, share, and the three
places in subsonic/library). This keeps NULL-disc tracks sorting
before disc-1 tracks, preserving pre-migration behavior for
all-NULL albums (the common case right after upgrade) and only
slightly reordering partially-rescanned multi-disc albums (rare,
and only until a full rescan completes).

Found during pre-release review.
This commit is contained in:
Your Name
2026-04-07 18:15:05 -05:00
parent 3cd48ddce2
commit d1bc273f00
4 changed files with 6 additions and 6 deletions
+1 -1
View File
@@ -119,7 +119,7 @@ router.get("/albums/:id", async (req, res) => {
},
tracks: {
orderBy: [
{ discNumber: Prisma.SortOrder.asc },
{ discNumber: { sort: Prisma.SortOrder.asc, nulls: "first" } },
{ trackNo: Prisma.SortOrder.asc },
],
},
+1 -1
View File
@@ -34,7 +34,7 @@ router.post("/albums/:id/download", async (req, res) => {
include: {
tracks: {
orderBy: [
{ discNumber: "asc" },
{ discNumber: { sort: "asc", nulls: "first" } },
{ trackNo: "asc" },
],
},
+1 -1
View File
@@ -208,7 +208,7 @@ router.get("/:token", shareResolveLimiter, async (req: Request, res: Response) =
artist: { select: { id: true, name: true } },
tracks: {
orderBy: [
{ discNumber: "asc" },
{ discNumber: { sort: "asc", nulls: "first" } },
{ trackNo: "asc" },
],
select: {
+3 -3
View File
@@ -135,7 +135,7 @@ libraryRouter.all("/getMusicDirectory.view", wrap(async (req, res) => {
tracks: {
where: { corrupt: false },
orderBy: [
{ discNumber: "asc" },
{ discNumber: { sort: "asc", nulls: "first" } },
{ trackNo: "asc" },
],
},
@@ -283,7 +283,7 @@ libraryRouter.all("/getMusicDirectory.view", wrap(async (req, res) => {
artist: { select: { id: true, name: true, displayName: true, genres: true, userGenres: true } },
tracks: {
orderBy: [
{ discNumber: "asc" },
{ discNumber: { sort: "asc", nulls: "first" } },
{ trackNo: "asc" },
],
},
@@ -325,7 +325,7 @@ libraryRouter.all("/getAlbum.view", wrap(async (req, res) => {
artist: { select: { id: true, name: true, displayName: true, genres: true, userGenres: true } },
tracks: {
orderBy: [
{ discNumber: "asc" },
{ discNumber: { sort: "asc", nulls: "first" } },
{ trackNo: "asc" },
],
},