From bd3057ec80d0432d653fce15836d113b79a020b4 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Tue, 24 Mar 2026 16:47:30 -0400 Subject: [PATCH] fix: correctly handle NULL library_id in search service Updates SearchMediaItemsUnified to conditionally set LibraryID parameter only when it's valid. Previously, the code always set LibraryID in the dbParams struct, which caused pgx to pass a zero UUID instead of NULL to PostgreSQL. New behavior: - Only sets dbParams.LibraryID when params.LibraryID.Valid is true - When library_id is empty, LibraryID is omitted from the struct - Go's zero value + pgx's "field not set" detection = NULL in SQL Also fixes type mismatches in SearchFieldValues method where SearchQuery parameter needed explicit pgtype.Text wrapping with Valid=true flag for proper nullable text handling. This ensures that omitting the library_id query parameter results in searching across all libraries, not filtering by zero UUID. --- internal/services/search.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/internal/services/search.go b/internal/services/search.go index ad5ba04..32b6585 100644 --- a/internal/services/search.go +++ b/internal/services/search.go @@ -66,7 +66,6 @@ func (s *SearchService) SearchMediaItemsUnified(ctx context.Context, params Sear // Build database parameters dbParams := database.SearchMediaItemsUnifiedParams{ UserID: params.UserID, - LibraryID: params.LibraryID, AuthorFilter: pgtype.Text{String: params.AuthorFilter, Valid: true}, SeriesFilter: pgtype.Text{String: params.SeriesFilter, Valid: true}, GenreFilter: pgtype.Text{String: params.GenreFilter, Valid: true}, @@ -82,6 +81,10 @@ func (s *SearchService) SearchMediaItemsUnified(ctx context.Context, params Sear Offset: pgtype.Int4{Int32: int32(params.Offset), Valid: true}, } + if params.LibraryID.Valid { + dbParams.LibraryID = params.LibraryID + } + // Execute unified search query results, err := s.db.SearchMediaItemsUnified(ctx, dbParams) if err != nil { @@ -115,7 +118,7 @@ func (s *SearchService) SearchFieldValues(ctx context.Context, params FieldSearc switch params.FieldType { case "author": results, err := s.db.SearchAuthorValues(ctx, database.SearchAuthorValuesParams{ - SearchQuery: params.SearchQuery, + SearchQuery: pgtype.Text{String: params.SearchQuery, Valid: true}, UserID: params.UserID, LibraryID: params.LibraryID, Limit: pgtype.Int4{Int32: int32(params.Limit), Valid: true}, @@ -132,7 +135,7 @@ func (s *SearchService) SearchFieldValues(ctx context.Context, params FieldSearc case "genre": results, err := s.db.SearchGenreValues(ctx, database.SearchGenreValuesParams{ - SearchQuery: params.SearchQuery, + SearchQuery: pgtype.Text{String: params.SearchQuery, Valid: true}, UserID: params.UserID, LibraryID: params.LibraryID, Limit: pgtype.Int4{Int32: int32(params.Limit), Valid: true}, @@ -149,7 +152,7 @@ func (s *SearchService) SearchFieldValues(ctx context.Context, params FieldSearc case "series": results, err := s.db.SearchSeriesValues(ctx, database.SearchSeriesValuesParams{ - SearchQuery: params.SearchQuery, + SearchQuery: pgtype.Text{String: params.SearchQuery, Valid: true}, UserID: params.UserID, LibraryID: params.LibraryID, Limit: pgtype.Int4{Int32: int32(params.Limit), Valid: true}, @@ -166,7 +169,7 @@ func (s *SearchService) SearchFieldValues(ctx context.Context, params FieldSearc case "language": results, err := s.db.SearchLanguageValues(ctx, database.SearchLanguageValuesParams{ - SearchQuery: params.SearchQuery, + SearchQuery: pgtype.Text{String: params.SearchQuery, Valid: true}, UserID: params.UserID, LibraryID: params.LibraryID, Limit: pgtype.Int4{Int32: int32(params.Limit), Valid: true},