Skip to content

WIP updates to allow postgres database connectivity - #644

Merged
bonukai merged 14 commits into
bonukai:wipfrom
ramebd:wip
Dec 2, 2024
Merged

WIP updates to allow postgres database connectivity#644
bonukai merged 14 commits into
bonukai:wipfrom
ramebd:wip

Conversation

@ramebd

@ramebd ramebd commented Nov 30, 2024

Copy link
Copy Markdown

I've made a few updates in the WIP branch which allow you to at least start MediaTracker and not generate a ton of db query complaints while using a postgres database. It should now also be a bit easier to allow connecting to mysql/mariadb, sql server or various others.

Commit 9244da9: fix option parsing to allow use of postgresql
Primarily, the application would not start when trying to configure postgres connection due to the db-filepath option being defaulted to . since db-connection-string and db-file-path are mutually exclusive and the program exits with error, this locked out anything except sqlite. Option parsing then didn't allow a value check to confirm which value of dbclient could be used with connection-string or filepath, so added in a .action() to validate. The validation throw new Error() should not actually get hit at any point, it's just there for safety.

Commit e47eeec: fix the error when picking the max seen date per mediaitem
This error was caused by trying to both select the date column and do a group-by on it, so a simple fix.

Commit 84f395d: fix issue with numeric values being returned as strings
Per the commit comment - This broke mediaItemModelSchema because mediaItem.tmdbRating is defined as a decimal(8,2) value, but the database query returned a string due to no implicit type conversion from decimal to float in typescript.
When the data query returned, and tried to map the data into rows of mediaItemModelSchema, tmdbRating errored because it would be a string value ie: "7.6" instead of just: 7.6. This is a base JS limitation of not having a suitable data type conversion for accurate decimal/numeric values (>32bit), only floats. Choices are to either:

  • change the data type in the database to float, int or string then deal with all conversions manually (ugh)
  • make tmdbRating a string in the data model and database (a bit icky and potential future issue)
  • accept that some accuracy might be lost by returning round(7.59999990463256836,2) instead of 7.6
    For tv and movie ratings, I think the minor accuracy variation is fine. If MediaTracker needs to store currency or high decimal accuracy values at some point, then perhaps a rethink here.

Commit ad17031: remove sortQuery when doing a simple count(*)
First part pretty straightforward - don't need to sort results to count em.
Second part is a re-write of the query to create a subquery for unseenEpisodesCount. sqlite can refer to dynamic column aliases in the where of the same select level, but postgres (and most other db's) cannot. generally, you can only use an alias in the result set, not the where, group-by, order-by or having at the same query level.

Commit 2bcba94: remove select * when doing a count()
Cloning the previous query to do a count(
) meant including select mediaItem.*, so all columns (or at least the pk) from mediaItem would have to be included in a group-by as well. Easier to just clear the selected columns and return only the count when that's all that's needed.

ERROR: error: select "date", "mediaItemId", max("date") as "date" from "seen" where "userId" = $1 and "mediaItemId" in ($2, $3) group by "mediaItemId" - column "seen.date" must appear in the GROUP BY clause or be used in an aggregate function
this broke mediaItemModelSchema because mediaItem.tmdbRating is defined as a decimal(8,2) value, but the database query returned a string due to no implicit type conversion from decimal to float in typescript
@bonukai

bonukai commented Nov 30, 2024

Copy link
Copy Markdown
Owner

Calculating upcoming and last aired episodes seems to be the last not working thing in pg: https://github.com/bonukai/MediaTracker/blob/wip/src/repository/mediaItemRepository.ts#L775-L849

error: update "mediaItem" set "upcomingEpisodeId" = (select "upcomingEpisode"."id" from "episode" left join (select "tvShowId", min("seasonAndEpisodeNumber") as "seasonAndEpisodeNumber" from "episode" where "isSpecialEpisode" = $1 and "releaseDate" > $2 group by "tvShowId") as "abc" on "abc"."tvShowId" = "mediaItem"."id" left join "episode" as "upcomingEpisode" on "abc"."tvShowId" = "upcomingEpisode"."tvShowId" and "abc"."seasonAndEpisodeNumber" = "upcomingEpisode"."seasonAndEpisodeNumber" where "episode"."tvShowId" = "mediaItem"."id") - more than one row returned by a subquery used as an expression

I have no clue how to fix it

This code updates upcomingEpisodeId in mediaItem table to the id of upcoming episode. This function is triggered for all tv shows when servers starts, and then after metadata updated and after a new episode has been released.

@bonukai

bonukai commented Dec 1, 2024

Copy link
Copy Markdown
Owner

Adding limit(1) seems to fix it, and it looks like it works correctly

@ramebd
ramebd marked this pull request as ready for review December 1, 2024 04:05
@ramebd

ramebd commented Dec 1, 2024

Copy link
Copy Markdown
Author

Calculating upcoming and last aired episodes seems to be the last not working thing in pg: https://github.com/bonukai/MediaTracker/blob/wip/src/repository/mediaItemRepository.ts#L775-L849

error: update "mediaItem" set "upcomingEpisodeId" = (select "upcomingEpisode"."id" from "episode" left join (select "tvShowId", min("seasonAndEpisodeNumber") as "seasonAndEpisodeNumber" from "episode" where "isSpecialEpisode" = $1 and "releaseDate" > $2 group by "tvShowId") as "abc" on "abc"."tvShowId" = "mediaItem"."id" left join "episode" as "upcomingEpisode" on "abc"."tvShowId" = "upcomingEpisode"."tvShowId" and "abc"."seasonAndEpisodeNumber" = "upcomingEpisode"."seasonAndEpisodeNumber" where "episode"."tvShowId" = "mediaItem"."id") - more than one row returned by a subquery used as an expression

I have no clue how to fix it

This code updates upcomingEpisodeId in mediaItem table to the id of upcoming episode. This function is triggered for all tv shows when servers starts, and then after metadata updated and after a new episode has been released.

Yep, that's an odd one since it looks like the episode table shouldn't allow either nulls or duplicates on those columns. Possibly some invalid data? Or seasonAndEpisodeNumber != seasonNumber and episodeNumber? Hard to say without seeing what's in the db, but perhaps its creating a cartesian with the other .leftJoin(). I was going to suggest a .first() as a hacky fix, but a .limit(1) does the same thing :)

@bonukai
bonukai merged commit f74a980 into bonukai:wip Dec 2, 2024
Comment thread src/repository/listRepository.ts Outdated
.leftJoin('mediaItem', 'listItem.mediaItemId', 'mediaItem.id')
.modify((qb) => filterQuery(qb, args))
.modify((qb) => sortQuery(qb, args))
//Dont need to sort when just doing a count(*)!

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, sorting by 'next-airing' removes items that do not have an 'next-airing', so filterQuery is required. I know, it's not a great design :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants