Sql cleanups

This commit is contained in:
Zoe Roux 2025-04-07 23:34:33 +02:00
parent 69006478cb
commit 4cf67c3247
No known key found for this signature in database
3 changed files with 25 additions and 19 deletions

View File

@ -187,7 +187,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
.select( .select(
db db
.select({ .select({
profilePk: sql<number>`${profilePk}`, profilePk: sql`${profilePk}`,
entryPk: entries.pk, entryPk: entries.pk,
videoPk: videos.pk, videoPk: videos.pk,
percent: sql`hist.percent::integer`, percent: sql`hist.percent::integer`,
@ -227,6 +227,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
), ),
) )
.orderBy(nextEntry.showPk, entries.order) .orderBy(nextEntry.showPk, entries.order)
.limit(1)
.as("nextEntryQ"); .as("nextEntryQ");
const seenCountQ = db const seenCountQ = db
@ -247,8 +248,7 @@ export const historyH = new Elysia({ tags: ["profiles"] })
), ),
), ),
), ),
) );
.as("seenCountQ");
await db await db
.insert(watchlist) .insert(watchlist)
@ -260,16 +260,16 @@ export const historyH = new Elysia({ tags: ["profiles"] })
status: sql` status: sql`
case case
when when
hist.progress >= 95 hist.percent::integer >= 95
and ${nextEntryQ.pk} is null and ${nextEntryQ.pk} is null
then 'completed'::watchstatus then 'completed'::watchlist_status
else 'watching'::watchstatus else 'watching'::watchlist_status
end end
`, `,
seenCount: sql` seenCount: sql`
case case
when ${eq(entries.kind, "movie")} then hist.progress::number when ${entries.kind} = 'movie' then hist.percent::integer
when hist.progress >= 95 then 1 when hist.percent::integer >= 95 then 1
else 0 else 0
end end
`, `,
@ -282,6 +282,8 @@ export const historyH = new Elysia({ tags: ["profiles"] })
else null else null
end end
`, `,
// see https://github.com/drizzle-team/drizzle-orm/issues/3608
updatedAt: sql`now()`,
}) })
.from(vals) .from(vals)
.leftJoin( .leftJoin(
@ -297,26 +299,26 @@ export const historyH = new Elysia({ tags: ["profiles"] })
), ),
), ),
) )
.leftLateralJoin(nextEntryQ, sql`true`), .leftJoinLateral(nextEntryQ, sql`true`),
) )
.onConflictDoUpdate({ .onConflictDoUpdate({
target: [watchlist.profilePk, watchlist.showPk], target: [watchlist.profilePk, watchlist.showPk],
set: { set: {
status: sql` status: sql`
case case
when ${eq(sql`excluded.status`, "completed")} then excluded.status when excluded.status = 'completed' then excluded.status
when ${and( when
ne(watchlist.status, "completed"), ${watchlist.status} != 'completed'
ne(watchlist.status, "rewatching"), and ${watchlist.status} != 'rewatching'
)} then excluded.status then excluded.status
else ${watchlist.status} else ${watchlist.status}
end end
`, `,
seenCount: sql`${seenCountQ.c}`, seenCount: sql`${seenCountQ}`,
nextEntry: sql` nextEntry: sql`
case case
when ${eq(watchlist.status, "completed")} then null when ${watchlist.status} = 'completed' then null
else excluded.nextEntry else excluded.next_entry
end end
`, `,
completedAt: coalesce( completedAt: coalesce(

View File

@ -95,10 +95,14 @@ export function values(items: Record<string, unknown>[]) {
}; };
} }
export const coalesce = <T>(val: SQL<T> | Column, def: SQL<T>) => { export const coalesce = <T>(val: SQL<T> | Column, def: SQL<T> | Column) => {
return sql<T>`coalesce(${val}, ${def})`; return sql<T>`coalesce(${val}, ${def})`;
}; };
export const nullif = <T>(val: SQL<T> | Column, eq: SQL<T>) => {
return sql<T>`nullif(${val}, ${eq})`;
};
export const jsonbObjectAgg = <T>(key: SQLWrapper, value: SQL<T>) => { export const jsonbObjectAgg = <T>(key: SQLWrapper, value: SQL<T>) => {
return sql< return sql<
Record<string, T> Record<string, T>

View File

@ -143,7 +143,7 @@ describe("Set & get history", () => {
expect(body.items[1].watchStatus).toMatchObject({ expect(body.items[1].watchStatus).toMatchObject({
status: "completed", status: "completed",
percent: 100, percent: 100,
startedAt: "2025-02-02 00:00:00+00", completedAt: "2025-02-02 00:00:00+00",
}); });
}); });
}); });