From 4cf67c3247e57ea83eebe0eda07c419d5fc9b2c4 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Mon, 7 Apr 2025 23:34:33 +0200 Subject: [PATCH] Sql cleanups --- api/src/controllers/profiles/history.ts | 36 +++++++++++++------------ api/src/db/utils.ts | 6 ++++- api/tests/series/history.test.ts | 2 +- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/api/src/controllers/profiles/history.ts b/api/src/controllers/profiles/history.ts index b12bfc4e..d37febc4 100644 --- a/api/src/controllers/profiles/history.ts +++ b/api/src/controllers/profiles/history.ts @@ -187,7 +187,7 @@ export const historyH = new Elysia({ tags: ["profiles"] }) .select( db .select({ - profilePk: sql`${profilePk}`, + profilePk: sql`${profilePk}`, entryPk: entries.pk, videoPk: videos.pk, percent: sql`hist.percent::integer`, @@ -227,6 +227,7 @@ export const historyH = new Elysia({ tags: ["profiles"] }) ), ) .orderBy(nextEntry.showPk, entries.order) + .limit(1) .as("nextEntryQ"); const seenCountQ = db @@ -247,8 +248,7 @@ export const historyH = new Elysia({ tags: ["profiles"] }) ), ), ), - ) - .as("seenCountQ"); + ); await db .insert(watchlist) @@ -260,16 +260,16 @@ export const historyH = new Elysia({ tags: ["profiles"] }) status: sql` case when - hist.progress >= 95 + hist.percent::integer >= 95 and ${nextEntryQ.pk} is null - then 'completed'::watchstatus - else 'watching'::watchstatus + then 'completed'::watchlist_status + else 'watching'::watchlist_status end `, seenCount: sql` case - when ${eq(entries.kind, "movie")} then hist.progress::number - when hist.progress >= 95 then 1 + when ${entries.kind} = 'movie' then hist.percent::integer + when hist.percent::integer >= 95 then 1 else 0 end `, @@ -282,6 +282,8 @@ export const historyH = new Elysia({ tags: ["profiles"] }) else null end `, + // see https://github.com/drizzle-team/drizzle-orm/issues/3608 + updatedAt: sql`now()`, }) .from(vals) .leftJoin( @@ -297,26 +299,26 @@ export const historyH = new Elysia({ tags: ["profiles"] }) ), ), ) - .leftLateralJoin(nextEntryQ, sql`true`), + .leftJoinLateral(nextEntryQ, sql`true`), ) .onConflictDoUpdate({ target: [watchlist.profilePk, watchlist.showPk], set: { status: sql` case - when ${eq(sql`excluded.status`, "completed")} then excluded.status - when ${and( - ne(watchlist.status, "completed"), - ne(watchlist.status, "rewatching"), - )} then excluded.status + when excluded.status = 'completed' then excluded.status + when + ${watchlist.status} != 'completed' + and ${watchlist.status} != 'rewatching' + then excluded.status else ${watchlist.status} end `, - seenCount: sql`${seenCountQ.c}`, + seenCount: sql`${seenCountQ}`, nextEntry: sql` case - when ${eq(watchlist.status, "completed")} then null - else excluded.nextEntry + when ${watchlist.status} = 'completed' then null + else excluded.next_entry end `, completedAt: coalesce( diff --git a/api/src/db/utils.ts b/api/src/db/utils.ts index c5ac3e2f..c8f6c940 100644 --- a/api/src/db/utils.ts +++ b/api/src/db/utils.ts @@ -95,10 +95,14 @@ export function values(items: Record[]) { }; } -export const coalesce = (val: SQL | Column, def: SQL) => { +export const coalesce = (val: SQL | Column, def: SQL | Column) => { return sql`coalesce(${val}, ${def})`; }; +export const nullif = (val: SQL | Column, eq: SQL) => { + return sql`nullif(${val}, ${eq})`; +}; + export const jsonbObjectAgg = (key: SQLWrapper, value: SQL) => { return sql< Record diff --git a/api/tests/series/history.test.ts b/api/tests/series/history.test.ts index be9581c3..9bc14696 100644 --- a/api/tests/series/history.test.ts +++ b/api/tests/series/history.test.ts @@ -143,7 +143,7 @@ describe("Set & get history", () => { expect(body.items[1].watchStatus).toMatchObject({ status: "completed", percent: 100, - startedAt: "2025-02-02 00:00:00+00", + completedAt: "2025-02-02 00:00:00+00", }); }); });