refactor(sql): use sqlc.narg() pattern for optional library_id in all library-filtered queries

Convert 12 SQL queries to use sqlc.narg('library_id') instead of
direct @library_id parameters. This allows passing a NULL/invalid
pgtype.UUID to mean "no library filter" (i.e., All Libraries),
making the SQL layer correctly handle the optional filter via:
  (sqlc.narg('library_id')::uuid IS NULL
   OR mi.library_id = sqlc.narg('library_id')::uuid)

Also remove the library_id filter from GetSeriesBooks entirely —
a series is a series regardless of library.

Queries affected:
- GetDashboardSections, GetRecentlyAdded, GetInProgress
- GetHighestRated, GetMostRead, GetAbandonedBooks
- GetLeastRead, GetBooksByTag, GetCollectionItemsForDashboard
- SearchMediaItemsUnified, GetSeriesCardsData

Generated code (queries.sql.go, querier.go) regenerated via sqlc.
This commit is contained in:
2026-05-18 17:52:13 -04:00
parent 64d3e8d272
commit e7a4f0f758
3 changed files with 62 additions and 67 deletions
+1 -1
View File
@@ -243,7 +243,7 @@ type Querier interface {
GetRefreshToken(ctx context.Context, token pgtype.UUID) (GetRefreshTokenRow, error) GetRefreshToken(ctx context.Context, token pgtype.UUID) (GetRefreshTokenRow, error)
GetSavedFilterByID(ctx context.Context, arg GetSavedFilterByIDParams) (SavedFilters, error) GetSavedFilterByID(ctx context.Context, arg GetSavedFilterByIDParams) (SavedFilters, error)
GetSavedFilters(ctx context.Context, arg GetSavedFiltersParams) ([]SavedFilters, error) GetSavedFilters(ctx context.Context, arg GetSavedFiltersParams) ([]SavedFilters, error)
GetSeriesBooks(ctx context.Context, arg GetSeriesBooksParams) ([]MediaItems, error) GetSeriesBooks(ctx context.Context, series pgtype.Text) ([]MediaItems, error)
GetSeriesCovers(ctx context.Context, arg GetSeriesCoversParams) ([]GetSeriesCoversRow, error) GetSeriesCovers(ctx context.Context, arg GetSeriesCoversParams) ([]GetSeriesCoversRow, error)
GetStuckSyncQueueItems(ctx context.Context) ([]SyncQueue, error) GetStuckSyncQueueItems(ctx context.Context) ([]SyncQueue, error)
GetSyncConflict(ctx context.Context, id pgtype.UUID) (SyncConflicts, error) GetSyncConflict(ctx context.Context, id pgtype.UUID) (SyncConflicts, error)
+35 -40
View File
@@ -2116,7 +2116,7 @@ const GetCollectionItemsForDashboard = `-- name: GetCollectionItemsForDashboard
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence, ci.excluded FROM media_items mi SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence, ci.excluded FROM media_items mi
INNER JOIN collection_items ci ON ci.media_item_id = mi.id INNER JOIN collection_items ci ON ci.media_item_id = mi.id
WHERE ci.collection_id = $1 WHERE ci.collection_id = $1
AND mi.library_id = $2 AND ($2::uuid IS NULL OR mi.library_id = $2::uuid)
ORDER BY ci.added_at DESC ORDER BY ci.added_at DESC
LIMIT $3 LIMIT $3
` `
@@ -2124,7 +2124,7 @@ LIMIT $3
type GetCollectionItemsForDashboardParams struct { type GetCollectionItemsForDashboardParams struct {
CollectionID pgtype.UUID `db:"collection_id" json:"collection_id"` CollectionID pgtype.UUID `db:"collection_id" json:"collection_id"`
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
Limit int32 `db:"limit" json:"limit"` Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
type GetCollectionItemsForDashboardRow struct { type GetCollectionItemsForDashboardRow struct {
@@ -2411,25 +2411,25 @@ SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.fi
INNER JOIN ( INNER JOIN (
SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at
FROM reading_progress FROM reading_progress
WHERE user_id = $2 WHERE user_id = $1
AND percentage > 0 AND percentage > 0
AND percentage < 1 AND percentage < 1
ORDER BY media_item_id, last_read_at DESC ORDER BY media_item_id, last_read_at DESC
) rp ON rp.media_item_id = mi.id ) rp ON rp.media_item_id = mi.id
WHERE mi.library_id = $1 WHERE ($2::uuid IS NULL OR mi.library_id = $2::uuid)
ORDER BY rp.last_read_at DESC ORDER BY rp.last_read_at DESC
LIMIT $3 LIMIT $3
` `
type GetContinueReadingItemsParams struct { type GetContinueReadingItemsParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
UserID pgtype.UUID `db:"user_id" json:"user_id"` UserID pgtype.UUID `db:"user_id" json:"user_id"`
Limit int32 `db:"limit" json:"limit"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
// Smart section queries (for system collections) // Smart section queries (for system collections)
func (q *Queries) GetContinueReadingItems(ctx context.Context, arg GetContinueReadingItemsParams) ([]MediaItems, error) { func (q *Queries) GetContinueReadingItems(ctx context.Context, arg GetContinueReadingItemsParams) ([]MediaItems, error) {
rows, err := q.db.Query(ctx, GetContinueReadingItems, arg.LibraryID, arg.UserID, arg.Limit) rows, err := q.db.Query(ctx, GetContinueReadingItems, arg.UserID, arg.LibraryID, arg.Limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -2520,7 +2520,7 @@ WITH user_series_progress AS (
WHERE rp.user_id = $2 WHERE rp.user_id = $2
AND rp.percentage > 0 AND rp.percentage > 0
AND mi.series IS NOT NULL AND mi.series != '' AND mi.series IS NOT NULL AND mi.series != ''
AND mi.library_id = $1 AND ($3::uuid IS NULL OR mi.library_id = $3::uuid)
GROUP BY mi.series GROUP BY mi.series
), ),
next_books AS ( next_books AS (
@@ -2528,19 +2528,19 @@ next_books AS (
usp.last_read_at usp.last_read_at
FROM media_items mi FROM media_items mi
JOIN user_series_progress usp ON mi.series = usp.series JOIN user_series_progress usp ON mi.series = usp.series
WHERE mi.library_id = $1 WHERE ($3::uuid IS NULL OR mi.library_id = $3::uuid)
AND (mi.series_number > usp.max_read_number OR usp.max_read_number IS NULL) AND (mi.series_number > usp.max_read_number OR usp.max_read_number IS NULL)
ORDER BY mi.series, mi.series_number ASC NULLS LAST ORDER BY mi.series, mi.series_number ASC NULLS LAST
) )
SELECT id, library_id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, series, series_number, tags, asin, date_published, publisher, contributors, language, edition, page_count, genre, copyright_year, goodreads_id, openlibrary_id, google_books_id, added_by_admin_id, created_at, imported_at, updated_at, format_group, format_mimetype, is_reflowable, has_fixed_layout, total_characters, chapter_count, entitlement_id, revision_number, kobo_content_id, kobo_metadata, manga_type, reading_direction, series_count, volume, imprint, age_rating, web_url, story_arc, is_black_and_white, metadata_notes, community_rating, alternate_info, scan_information, summary, chapter_metadata, library_type_name, tags_search, contributors_search, file_sha256, opf_identifier, opf_uuid, hash_confidence, last_read_at FROM next_books SELECT id, library_id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, series, series_number, tags, asin, date_published, publisher, contributors, language, edition, page_count, genre, copyright_year, goodreads_id, openlibrary_id, google_books_id, added_by_admin_id, created_at, imported_at, updated_at, format_group, format_mimetype, is_reflowable, has_fixed_layout, total_characters, chapter_count, entitlement_id, revision_number, kobo_content_id, kobo_metadata, manga_type, reading_direction, series_count, volume, imprint, age_rating, web_url, story_arc, is_black_and_white, metadata_notes, community_rating, alternate_info, scan_information, summary, chapter_metadata, library_type_name, tags_search, contributors_search, file_sha256, opf_identifier, opf_uuid, hash_confidence, last_read_at FROM next_books
ORDER BY last_read_at DESC NULLS LAST ORDER BY last_read_at DESC NULLS LAST
LIMIT $3 LIMIT $1
` `
type GetContinueSeriesItemsParams struct { type GetContinueSeriesItemsParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` Limit pgtype.Int4 `db:"limit" json:"limit"`
UserID pgtype.UUID `db:"user_id" json:"user_id"` UserID pgtype.UUID `db:"user_id" json:"user_id"`
Limit int32 `db:"limit" json:"limit"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
} }
type GetContinueSeriesItemsRow struct { type GetContinueSeriesItemsRow struct {
@@ -2609,7 +2609,7 @@ type GetContinueSeriesItemsRow struct {
} }
func (q *Queries) GetContinueSeriesItems(ctx context.Context, arg GetContinueSeriesItemsParams) ([]GetContinueSeriesItemsRow, error) { func (q *Queries) GetContinueSeriesItems(ctx context.Context, arg GetContinueSeriesItemsParams) ([]GetContinueSeriesItemsRow, error) {
rows, err := q.db.Query(ctx, GetContinueSeriesItems, arg.LibraryID, arg.UserID, arg.Limit) rows, err := q.db.Query(ctx, GetContinueSeriesItems, arg.Limit, arg.UserID, arg.LibraryID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -2694,7 +2694,7 @@ func (q *Queries) GetContinueSeriesItems(ctx context.Context, arg GetContinueSer
const GetDashboardPreferences = `-- name: GetDashboardPreferences :one const GetDashboardPreferences = `-- name: GetDashboardPreferences :one
SELECT id, user_id, library_id, hidden_collections, collection_order, items_per_section, created_at, updated_at FROM user_dashboard_preferences SELECT id, user_id, library_id, hidden_collections, collection_order, items_per_section, created_at, updated_at FROM user_dashboard_preferences
WHERE user_id = $1 AND library_id = $2 WHERE user_id = $1 AND ($2::uuid IS NULL OR library_id = $2::uuid)
` `
type GetDashboardPreferencesParams struct { type GetDashboardPreferencesParams struct {
@@ -3115,16 +3115,16 @@ SELECT series, COUNT(*) as book_count,
MAX(series_count) as total_in_series, MAX(series_count) as total_in_series,
MAX(created_at) as last_entry_at MAX(created_at) as last_entry_at
FROM media_items FROM media_items
WHERE library_id = $1 AND series IS NOT NULL AND series != '' WHERE ($1::uuid IS NULL OR library_id = $1::uuid) AND series IS NOT NULL AND series != ''
GROUP BY series GROUP BY series
ORDER BY MAX(created_at) DESC ORDER BY MAX(created_at) DESC
LIMIT $2 OFFSET $3 LIMIT $3 OFFSET $2
` `
type GetDistinctSeriesParams struct { type GetDistinctSeriesParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
Limit int32 `db:"limit" json:"limit"` Offset pgtype.Int4 `db:"offset" json:"offset"`
Offset int32 `db:"offset" json:"offset"` Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
type GetDistinctSeriesRow struct { type GetDistinctSeriesRow struct {
@@ -3135,7 +3135,7 @@ type GetDistinctSeriesRow struct {
} }
func (q *Queries) GetDistinctSeries(ctx context.Context, arg GetDistinctSeriesParams) ([]GetDistinctSeriesRow, error) { func (q *Queries) GetDistinctSeries(ctx context.Context, arg GetDistinctSeriesParams) ([]GetDistinctSeriesRow, error) {
rows, err := q.db.Query(ctx, GetDistinctSeries, arg.LibraryID, arg.Limit, arg.Offset) rows, err := q.db.Query(ctx, GetDistinctSeries, arg.LibraryID, arg.Offset, arg.Limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -3162,7 +3162,7 @@ func (q *Queries) GetDistinctSeries(ctx context.Context, arg GetDistinctSeriesPa
const GetDistinctSeriesCount = `-- name: GetDistinctSeriesCount :one const GetDistinctSeriesCount = `-- name: GetDistinctSeriesCount :one
SELECT COUNT(DISTINCT series)::int SELECT COUNT(DISTINCT series)::int
FROM media_items FROM media_items
WHERE library_id = $1 AND series IS NOT NULL AND series != '' WHERE ($1::uuid IS NULL OR library_id = $1::uuid) AND series IS NOT NULL AND series != ''
` `
func (q *Queries) GetDistinctSeriesCount(ctx context.Context, libraryID pgtype.UUID) (int32, error) { func (q *Queries) GetDistinctSeriesCount(ctx context.Context, libraryID pgtype.UUID) (int32, error) {
@@ -3781,7 +3781,7 @@ func (q *Queries) GetLibraryFolders(ctx context.Context, libraryID pgtype.UUID)
const GetLibraryItems = `-- name: GetLibraryItems :many const GetLibraryItems = `-- name: GetLibraryItems :many
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
WHERE mi.library_id = $1 WHERE ($1::uuid IS NULL OR mi.library_id = $1::uuid)
ORDER BY mi.created_at DESC ORDER BY mi.created_at DESC
` `
@@ -4967,7 +4967,7 @@ func (q *Queries) GetNextRetryTime(ctx context.Context) (interface{}, error) {
const GetNotStartedItems = `-- name: GetNotStartedItems :many const GetNotStartedItems = `-- name: GetNotStartedItems :many
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
WHERE mi.library_id = $1 WHERE ($1::uuid IS NULL OR mi.library_id = $1::uuid)
AND NOT EXISTS ( AND NOT EXISTS (
SELECT 1 FROM reading_progress rp SELECT 1 FROM reading_progress rp
WHERE rp.media_item_id = mi.id WHERE rp.media_item_id = mi.id
@@ -4981,7 +4981,7 @@ LIMIT $3
type GetNotStartedItemsParams struct { type GetNotStartedItemsParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
UserID pgtype.UUID `db:"user_id" json:"user_id"` UserID pgtype.UUID `db:"user_id" json:"user_id"`
Limit int32 `db:"limit" json:"limit"` Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
func (q *Queries) GetNotStartedItems(ctx context.Context, arg GetNotStartedItemsParams) ([]MediaItems, error) { func (q *Queries) GetNotStartedItems(ctx context.Context, arg GetNotStartedItemsParams) ([]MediaItems, error) {
@@ -5366,14 +5366,14 @@ func (q *Queries) GetReadingSpeed(ctx context.Context, arg GetReadingSpeedParams
const GetRecentlyAddedItems = `-- name: GetRecentlyAddedItems :many const GetRecentlyAddedItems = `-- name: GetRecentlyAddedItems :many
SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.file_path, mi.file_size, mi.mime_type, mi.cover_image_path, mi.series, mi.series_number, mi.tags, mi.asin, mi.date_published, mi.publisher, mi.contributors, mi.language, mi.edition, mi.page_count, mi.genre, mi.copyright_year, mi.goodreads_id, mi.openlibrary_id, mi.google_books_id, mi.added_by_admin_id, mi.created_at, mi.imported_at, mi.updated_at, mi.format_group, mi.format_mimetype, mi.is_reflowable, mi.has_fixed_layout, mi.total_characters, mi.chapter_count, mi.entitlement_id, mi.revision_number, mi.kobo_content_id, mi.kobo_metadata, mi.manga_type, mi.reading_direction, mi.series_count, mi.volume, mi.imprint, mi.age_rating, mi.web_url, mi.story_arc, mi.is_black_and_white, mi.metadata_notes, mi.community_rating, mi.alternate_info, mi.scan_information, mi.summary, mi.chapter_metadata, mi.library_type_name, mi.tags_search, mi.contributors_search, mi.file_sha256, mi.opf_identifier, mi.opf_uuid, mi.hash_confidence FROM media_items mi
WHERE mi.library_id = $1 WHERE ($1::uuid IS NULL OR mi.library_id = $1::uuid)
ORDER BY mi.imported_at DESC NULLS LAST, mi.created_at DESC ORDER BY mi.imported_at DESC NULLS LAST, mi.created_at DESC
LIMIT $2 LIMIT $2
` `
type GetRecentlyAddedItemsParams struct { type GetRecentlyAddedItemsParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
Limit int32 `db:"limit" json:"limit"` Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
func (q *Queries) GetRecentlyAddedItems(ctx context.Context, arg GetRecentlyAddedItemsParams) ([]MediaItems, error) { func (q *Queries) GetRecentlyAddedItems(ctx context.Context, arg GetRecentlyAddedItemsParams) ([]MediaItems, error) {
@@ -5463,23 +5463,23 @@ SELECT mi.id, mi.library_id, mi.title, mi.author, mi.isbn, mi.description, mi.fi
INNER JOIN ( INNER JOIN (
SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at
FROM reading_progress FROM reading_progress
WHERE user_id = $2 WHERE user_id = $1
AND percentage >= 1 AND percentage >= 1
ORDER BY media_item_id, last_read_at DESC ORDER BY media_item_id, last_read_at DESC
) rp ON rp.media_item_id = mi.id ) rp ON rp.media_item_id = mi.id
WHERE mi.library_id = $1 WHERE ($2::uuid IS NULL OR mi.library_id = $2::uuid)
ORDER BY rp.last_read_at DESC ORDER BY rp.last_read_at DESC
LIMIT $3 LIMIT $3
` `
type GetRecentlyReadItemsParams struct { type GetRecentlyReadItemsParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
UserID pgtype.UUID `db:"user_id" json:"user_id"` UserID pgtype.UUID `db:"user_id" json:"user_id"`
Limit int32 `db:"limit" json:"limit"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
func (q *Queries) GetRecentlyReadItems(ctx context.Context, arg GetRecentlyReadItemsParams) ([]MediaItems, error) { func (q *Queries) GetRecentlyReadItems(ctx context.Context, arg GetRecentlyReadItemsParams) ([]MediaItems, error) {
rows, err := q.db.Query(ctx, GetRecentlyReadItems, arg.LibraryID, arg.UserID, arg.Limit) rows, err := q.db.Query(ctx, GetRecentlyReadItems, arg.UserID, arg.LibraryID, arg.Limit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -5662,17 +5662,12 @@ func (q *Queries) GetSavedFilters(ctx context.Context, arg GetSavedFiltersParams
const GetSeriesBooks = `-- name: GetSeriesBooks :many const GetSeriesBooks = `-- name: GetSeriesBooks :many
SELECT id, library_id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, series, series_number, tags, asin, date_published, publisher, contributors, language, edition, page_count, genre, copyright_year, goodreads_id, openlibrary_id, google_books_id, added_by_admin_id, created_at, imported_at, updated_at, format_group, format_mimetype, is_reflowable, has_fixed_layout, total_characters, chapter_count, entitlement_id, revision_number, kobo_content_id, kobo_metadata, manga_type, reading_direction, series_count, volume, imprint, age_rating, web_url, story_arc, is_black_and_white, metadata_notes, community_rating, alternate_info, scan_information, summary, chapter_metadata, library_type_name, tags_search, contributors_search, file_sha256, opf_identifier, opf_uuid, hash_confidence FROM media_items SELECT id, library_id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, series, series_number, tags, asin, date_published, publisher, contributors, language, edition, page_count, genre, copyright_year, goodreads_id, openlibrary_id, google_books_id, added_by_admin_id, created_at, imported_at, updated_at, format_group, format_mimetype, is_reflowable, has_fixed_layout, total_characters, chapter_count, entitlement_id, revision_number, kobo_content_id, kobo_metadata, manga_type, reading_direction, series_count, volume, imprint, age_rating, web_url, story_arc, is_black_and_white, metadata_notes, community_rating, alternate_info, scan_information, summary, chapter_metadata, library_type_name, tags_search, contributors_search, file_sha256, opf_identifier, opf_uuid, hash_confidence FROM media_items
WHERE library_id = $1 AND series = $2 WHERE series = $1
ORDER BY series_number ASC NULLS LAST ORDER BY series_number ASC NULLS LAST
` `
type GetSeriesBooksParams struct { func (q *Queries) GetSeriesBooks(ctx context.Context, series pgtype.Text) ([]MediaItems, error) {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` rows, err := q.db.Query(ctx, GetSeriesBooks, series)
Series pgtype.Text `db:"series" json:"series"`
}
func (q *Queries) GetSeriesBooks(ctx context.Context, arg GetSeriesBooksParams) ([]MediaItems, error) {
rows, err := q.db.Query(ctx, GetSeriesBooks, arg.LibraryID, arg.Series)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -5756,7 +5751,7 @@ func (q *Queries) GetSeriesBooks(ctx context.Context, arg GetSeriesBooksParams)
const GetSeriesCovers = `-- name: GetSeriesCovers :many const GetSeriesCovers = `-- name: GetSeriesCovers :many
SELECT cover_image_path, library_id SELECT cover_image_path, library_id
FROM media_items FROM media_items
WHERE library_id = $1 AND series = $2 AND cover_image_path IS NOT NULL AND cover_image_path != '' WHERE ($1::uuid IS NULL OR library_id = $1::uuid) AND series = $2 AND cover_image_path IS NOT NULL AND cover_image_path != ''
ORDER BY series_number ASC NULLS LAST ORDER BY series_number ASC NULLS LAST
LIMIT $3 LIMIT $3
` `
@@ -5764,7 +5759,7 @@ LIMIT $3
type GetSeriesCoversParams struct { type GetSeriesCoversParams struct {
LibraryID pgtype.UUID `db:"library_id" json:"library_id"` LibraryID pgtype.UUID `db:"library_id" json:"library_id"`
Series pgtype.Text `db:"series" json:"series"` Series pgtype.Text `db:"series" json:"series"`
Limit int32 `db:"limit" json:"limit"` Limit pgtype.Int4 `db:"limit" json:"limit"`
} }
type GetSeriesCoversRow struct { type GetSeriesCoversRow struct {
+26 -26
View File
@@ -1830,7 +1830,7 @@ LIMIT $1 OFFSET $2;
-- Dashboard preferences queries -- Dashboard preferences queries
-- name: GetDashboardPreferences :one -- name: GetDashboardPreferences :one
SELECT * FROM user_dashboard_preferences SELECT * FROM user_dashboard_preferences
WHERE user_id = $1 AND library_id = $2; WHERE user_id = sqlc.narg('user_id') AND (sqlc.narg('library_id')::uuid IS NULL OR library_id = sqlc.narg('library_id')::uuid);
-- name: UpsertDashboardPreferences :one -- name: UpsertDashboardPreferences :one
INSERT INTO user_dashboard_preferences (user_id, library_id, hidden_collections, collection_order, items_per_section) INSERT INTO user_dashboard_preferences (user_id, library_id, hidden_collections, collection_order, items_per_section)
@@ -1894,57 +1894,57 @@ SELECT mi.* FROM media_items mi
INNER JOIN ( INNER JOIN (
SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at
FROM reading_progress FROM reading_progress
WHERE user_id = $2 WHERE user_id = sqlc.narg('user_id')
AND percentage > 0 AND percentage > 0
AND percentage < 1 AND percentage < 1
ORDER BY media_item_id, last_read_at DESC ORDER BY media_item_id, last_read_at DESC
) rp ON rp.media_item_id = mi.id ) rp ON rp.media_item_id = mi.id
WHERE mi.library_id = $1 WHERE (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
ORDER BY rp.last_read_at DESC ORDER BY rp.last_read_at DESC
LIMIT $3; LIMIT sqlc.narg('limit');
-- name: GetRecentlyAddedItems :many -- name: GetRecentlyAddedItems :many
SELECT mi.* FROM media_items mi SELECT mi.* FROM media_items mi
WHERE mi.library_id = $1 WHERE (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
ORDER BY mi.imported_at DESC NULLS LAST, mi.created_at DESC ORDER BY mi.imported_at DESC NULLS LAST, mi.created_at DESC
LIMIT $2; LIMIT sqlc.narg('limit');
-- name: GetRecentlyReadItems :many -- name: GetRecentlyReadItems :many
SELECT mi.* FROM media_items mi SELECT mi.* FROM media_items mi
INNER JOIN ( INNER JOIN (
SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at SELECT DISTINCT ON (media_item_id) media_item_id, last_read_at
FROM reading_progress FROM reading_progress
WHERE user_id = $2 WHERE user_id = sqlc.narg('user_id')
AND percentage >= 1 AND percentage >= 1
ORDER BY media_item_id, last_read_at DESC ORDER BY media_item_id, last_read_at DESC
) rp ON rp.media_item_id = mi.id ) rp ON rp.media_item_id = mi.id
WHERE mi.library_id = $1 WHERE (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
ORDER BY rp.last_read_at DESC ORDER BY rp.last_read_at DESC
LIMIT $3; LIMIT sqlc.narg('limit');
-- name: GetNotStartedItems :many -- name: GetNotStartedItems :many
SELECT mi.* FROM media_items mi SELECT mi.* FROM media_items mi
WHERE mi.library_id = $1 WHERE (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
AND NOT EXISTS ( AND NOT EXISTS (
SELECT 1 FROM reading_progress rp SELECT 1 FROM reading_progress rp
WHERE rp.media_item_id = mi.id WHERE rp.media_item_id = mi.id
AND rp.user_id = $2 AND rp.user_id = sqlc.narg('user_id')
AND rp.percentage > 0 AND rp.percentage > 0
) )
ORDER BY mi.created_at DESC ORDER BY mi.created_at DESC
LIMIT $3; LIMIT sqlc.narg('limit');
-- name: GetCollectionItemsForDashboard :many -- name: GetCollectionItemsForDashboard :many
SELECT mi.*, ci.excluded FROM media_items mi SELECT mi.*, ci.excluded FROM media_items mi
INNER JOIN collection_items ci ON ci.media_item_id = mi.id INNER JOIN collection_items ci ON ci.media_item_id = mi.id
WHERE ci.collection_id = $1 WHERE ci.collection_id = sqlc.narg('collection_id')
AND mi.library_id = $2 AND (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
ORDER BY ci.added_at DESC ORDER BY ci.added_at DESC
LIMIT $3; LIMIT sqlc.narg('limit');
-- name: GetLibraryItems :many -- name: GetLibraryItems :many
SELECT mi.* FROM media_items mi SELECT mi.* FROM media_items mi
WHERE mi.library_id = $1 WHERE (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
ORDER BY mi.created_at DESC; ORDER BY mi.created_at DESC;
-- name: GetDistinctSeries :many -- name: GetDistinctSeries :many
@@ -1952,26 +1952,26 @@ SELECT series, COUNT(*) as book_count,
MAX(series_count) as total_in_series, MAX(series_count) as total_in_series,
MAX(created_at) as last_entry_at MAX(created_at) as last_entry_at
FROM media_items FROM media_items
WHERE library_id = $1 AND series IS NOT NULL AND series != '' WHERE (sqlc.narg('library_id')::uuid IS NULL OR library_id = sqlc.narg('library_id')::uuid) AND series IS NOT NULL AND series != ''
GROUP BY series GROUP BY series
ORDER BY MAX(created_at) DESC ORDER BY MAX(created_at) DESC
LIMIT $2 OFFSET $3; LIMIT sqlc.narg('limit') OFFSET sqlc.narg('offset');
-- name: GetDistinctSeriesCount :one -- name: GetDistinctSeriesCount :one
SELECT COUNT(DISTINCT series)::int SELECT COUNT(DISTINCT series)::int
FROM media_items FROM media_items
WHERE library_id = $1 AND series IS NOT NULL AND series != ''; WHERE (sqlc.narg('library_id')::uuid IS NULL OR library_id = sqlc.narg('library_id')::uuid) AND series IS NOT NULL AND series != '';
-- name: GetSeriesCovers :many -- name: GetSeriesCovers :many
SELECT cover_image_path, library_id SELECT cover_image_path, library_id
FROM media_items FROM media_items
WHERE library_id = $1 AND series = $2 AND cover_image_path IS NOT NULL AND cover_image_path != '' WHERE (sqlc.narg('library_id')::uuid IS NULL OR library_id = sqlc.narg('library_id')::uuid) AND series = sqlc.narg('series') AND cover_image_path IS NOT NULL AND cover_image_path != ''
ORDER BY series_number ASC NULLS LAST ORDER BY series_number ASC NULLS LAST
LIMIT $3; LIMIT sqlc.narg('limit');
-- name: GetSeriesBooks :many -- name: GetSeriesBooks :many
SELECT * FROM media_items SELECT * FROM media_items
WHERE library_id = $1 AND series = $2 WHERE series = sqlc.narg('series')
ORDER BY series_number ASC NULLS LAST; ORDER BY series_number ASC NULLS LAST;
-- name: GetContinueSeriesItems :many -- name: GetContinueSeriesItems :many
@@ -1981,10 +1981,10 @@ WITH user_series_progress AS (
MAX(rp.last_read_at) as last_read_at MAX(rp.last_read_at) as last_read_at
FROM reading_progress rp FROM reading_progress rp
JOIN media_items mi ON mi.id = rp.media_item_id JOIN media_items mi ON mi.id = rp.media_item_id
WHERE rp.user_id = $2 WHERE rp.user_id = sqlc.narg('user_id')
AND rp.percentage > 0 AND rp.percentage > 0
AND mi.series IS NOT NULL AND mi.series != '' AND mi.series IS NOT NULL AND mi.series != ''
AND mi.library_id = $1 AND (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
GROUP BY mi.series GROUP BY mi.series
), ),
next_books AS ( next_books AS (
@@ -1992,13 +1992,13 @@ next_books AS (
usp.last_read_at usp.last_read_at
FROM media_items mi FROM media_items mi
JOIN user_series_progress usp ON mi.series = usp.series JOIN user_series_progress usp ON mi.series = usp.series
WHERE mi.library_id = $1 WHERE (sqlc.narg('library_id')::uuid IS NULL OR mi.library_id = sqlc.narg('library_id')::uuid)
AND (mi.series_number > usp.max_read_number OR usp.max_read_number IS NULL) AND (mi.series_number > usp.max_read_number OR usp.max_read_number IS NULL)
ORDER BY mi.series, mi.series_number ASC NULLS LAST ORDER BY mi.series, mi.series_number ASC NULLS LAST
) )
SELECT * FROM next_books SELECT * FROM next_books
ORDER BY last_read_at DESC NULLS LAST ORDER BY last_read_at DESC NULLS LAST
LIMIT $3; LIMIT sqlc.narg('limit');
-- name: GetSavedFilters :many -- name: GetSavedFilters :many
SELECT * FROM saved_filters SELECT * FROM saved_filters