From 647dec676fb7dce14ea98e932eab168347bb40ef Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 10 May 2026 16:11:46 -0400 Subject: [PATCH] feat(db): add GetBooksByTag query for tag detail page Uses $2 = ANY(tags) to match against the tags text[] column with GIN index support. sqlc generates a single string Column2 param (not []string). --- internal/database/querier.go | 1 + internal/database/queries.sql.go | 92 +++++++++++++++++++++++++++ internal/database/queries/queries.sql | 5 ++ 3 files changed, 98 insertions(+) diff --git a/internal/database/querier.go b/internal/database/querier.go index 95fe1c6..7e50a2f 100644 --- a/internal/database/querier.go +++ b/internal/database/querier.go @@ -129,6 +129,7 @@ type Querier interface { GetAllSystemConfig(ctx context.Context) ([]SystemConfig, error) GetAllSystemSettings(ctx context.Context) ([]GetAllSystemSettingsRow, error) GetAnnotationsForBook(ctx context.Context, arg GetAnnotationsForBookParams) ([]GetAnnotationsForBookRow, error) + GetBooksByTag(ctx context.Context, arg GetBooksByTagParams) ([]MediaItems, error) // Get collection GetCollection(ctx context.Context, id pgtype.UUID) (Collections, error) // Get collection items diff --git a/internal/database/queries.sql.go b/internal/database/queries.sql.go index 5931058..9599d30 100644 --- a/internal/database/queries.sql.go +++ b/internal/database/queries.sql.go @@ -1937,6 +1937,98 @@ func (q *Queries) GetAnnotationsForBook(ctx context.Context, arg GetAnnotationsF return items, nil } +const GetBooksByTag = `-- name: GetBooksByTag :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, 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 tags @> ARRAY[$2::text] +ORDER BY title ASC +` + +type GetBooksByTagParams struct { + LibraryID pgtype.UUID `db:"library_id" json:"library_id"` + Column2 string `db:"column_2" json:"column_2"` +} + +func (q *Queries) GetBooksByTag(ctx context.Context, arg GetBooksByTagParams) ([]MediaItems, error) { + rows, err := q.db.Query(ctx, GetBooksByTag, arg.LibraryID, arg.Column2) + if err != nil { + return nil, err + } + defer rows.Close() + items := []MediaItems{} + for rows.Next() { + var i MediaItems + if err := rows.Scan( + &i.ID, + &i.LibraryID, + &i.Title, + &i.Author, + &i.Isbn, + &i.Description, + &i.FilePath, + &i.FileSize, + &i.MimeType, + &i.CoverImagePath, + &i.Series, + &i.SeriesNumber, + &i.Tags, + &i.Asin, + &i.DatePublished, + &i.Publisher, + &i.Contributors, + &i.Language, + &i.Edition, + &i.PageCount, + &i.Genre, + &i.CopyrightYear, + &i.GoodreadsID, + &i.OpenlibraryID, + &i.GoogleBooksID, + &i.AddedByAdminID, + &i.CreatedAt, + &i.UpdatedAt, + &i.FormatGroup, + &i.FormatMimetype, + &i.IsReflowable, + &i.HasFixedLayout, + &i.TotalCharacters, + &i.ChapterCount, + &i.EntitlementID, + &i.RevisionNumber, + &i.KoboContentID, + &i.KoboMetadata, + &i.MangaType, + &i.ReadingDirection, + &i.SeriesCount, + &i.Volume, + &i.Imprint, + &i.AgeRating, + &i.WebUrl, + &i.StoryArc, + &i.IsBlackAndWhite, + &i.MetadataNotes, + &i.CommunityRating, + &i.AlternateInfo, + &i.ScanInformation, + &i.Summary, + &i.ChapterMetadata, + &i.LibraryTypeName, + &i.TagsSearch, + &i.ContributorsSearch, + &i.FileSha256, + &i.OpfIdentifier, + &i.OpfUuid, + &i.HashConfidence, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const GetCollection = `-- name: GetCollection :one SELECT id, user_id, name, description, color, icon, auto_assign_rules, view_settings, show_on_dashboard, query_type, priority, is_system_collection, created_at FROM collections WHERE id = $1 ` diff --git a/internal/database/queries/queries.sql b/internal/database/queries/queries.sql index 3a5a440..3fa8efe 100644 --- a/internal/database/queries/queries.sql +++ b/internal/database/queries/queries.sql @@ -2167,3 +2167,8 @@ SELECT FROM libraries l JOIN library_types lt ON l.library_type_id = lt.id WHERE l.id = $1; + +-- name: GetBooksByTag :many +SELECT * FROM media_items +WHERE library_id = $1 AND tags @> ARRAY[$2::text] +ORDER BY title ASC;