diff --git a/modules/backend/handlers/users.go b/modules/backend/handlers/users.go index 0420b91..1ea2c1a 100644 --- a/modules/backend/handlers/users.go +++ b/modules/backend/handlers/users.go @@ -103,33 +103,23 @@ func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersU return oapi.GetUsersUserIdTitles400Response{}, err } - // Forward bool `json:"forward"` - // SortBy string `json:"sort_by"` - // CursorYear *int32 `json:"cursor_year"` - // CursorID *int64 `json:"cursor_id"` - // CursorRating *float64 `json:"cursor_rating"` - // Word *string `json:"word"` - // Ongoing string `json:"ongoing"` - // Planned string `json:"planned"` - // Dropped string `json:"dropped"` - // InProgress string `json:"in-progress"` - // Finished string `json:"finished"` - // Rate *int32 `json:"rate"` - // Rating *float64 `json:"rating"` - // ReleaseYear *int32 `json:"release_year"` - // ReleaseSeason *ReleaseSeasonT `json:"release_season"` - // Limit *int32 `json:"limit"` - params := sqlc.SearchTitlesParams{ - Word: word, - Ongoing: status.ongoing, - Finished: status.finished, - Planned: status.planned, - Rating: request.Params.Rating, - ReleaseYear: request.Params.ReleaseYear, - ReleaseSeason: season, - Forward: true, - SortBy: "id", - Limit: request.Params.Limit, + params := sqlc.SearchUserTitlesParams{ + Forward: true, + SortBy: "id", + // CursorYear : + // CursorID *int64 `json:"cursor_id"` + // CursorRating *float64 `json:"cursor_rating"` + // Word *string `json:"word"` + // Ongoing string `json:"ongoing"` + // Planned string `json:"planned"` + // Dropped string `json:"dropped"` + // InProgress string `json:"in-progress"` + // Finished string `json:"finished"` + // Rate *int32 `json:"rate"` + // Rating *float64 `json:"rating"` + // ReleaseYear *int32 `json:"release_year"` + // ReleaseSeason *ReleaseSeasonT `json:"release_season"` + // Limit *int32 `json:"limit"` } if request.Params.SortForward != nil { @@ -141,32 +131,42 @@ func (s Server) GetUsersUserIdTitles(ctx context.Context, request oapi.GetUsersU err := ParseCursorInto(string(*request.Params.Sort), string(*request.Params.Cursor), ¶ms) if err != nil { log.Errorf("%v", err) - return oapi.GetTitles400Response{}, nil + return oapi.GetUsersUserIdTitles400Response{}, nil } } } - - _sqlc_title := sqlc.SearchTitlesRow{ - ID: sqlc_title.ID, - StudioID: sqlc_title.StudioID, - PosterID: sqlc_title.PosterID, - TitleStatus: sqlc_title.TitleStatus, - Rating: sqlc_title.Rating, - RatingCount: sqlc_title.RatingCount, - ReleaseYear: sqlc_title.ReleaseYear, - ReleaseSeason: sqlc_title.ReleaseSeason, - Season: sqlc_title.Season, - EpisodesAired: sqlc_title.EpisodesAired, - EpisodesAll: sqlc_title.EpisodesAll, - EpisodesLen: sqlc_title.EpisodesLen, - TitleStorageType: sqlc_title.TitleStorageType, - TitleImagePath: sqlc_title.TitleImagePath, - TagNames: sqlc_title.TitleNames, - StudioName: sqlc_title.StudioName, - StudioIllustID: sqlc_title.StudioIllustID, - StudioDesc: sqlc_title.StudioDesc, - StudioStorageType: sqlc_title.StudioStorageType, - StudioImagePath: sqlc_title.StudioImagePath, + // param = nil means it will not be used + titles, err := s.db.SearchUserTitles(ctx, params) + if err != nil { + log.Errorf("%v", err) + return oapi.GetUsersUserIdTitles500Response{}, nil + } + if len(titles) == 0 { + return oapi.GetUsersUserIdTitles204Response{}, nil + } + for _, title := range titles { + _sqlc_title := sqlc.SearchTitlesRow{ + ID: sqlc_title.ID, + StudioID: sqlc_title.StudioID, + PosterID: sqlc_title.PosterID, + TitleStatus: sqlc_title.TitleStatus, + Rating: sqlc_title.Rating, + RatingCount: sqlc_title.RatingCount, + ReleaseYear: sqlc_title.ReleaseYear, + ReleaseSeason: sqlc_title.ReleaseSeason, + Season: sqlc_title.Season, + EpisodesAired: sqlc_title.EpisodesAired, + EpisodesAll: sqlc_title.EpisodesAll, + EpisodesLen: sqlc_title.EpisodesLen, + TitleStorageType: sqlc_title.TitleStorageType, + TitleImagePath: sqlc_title.TitleImagePath, + TagNames: sqlc_title.TitleNames, + StudioName: sqlc_title.StudioName, + StudioIllustID: sqlc_title.StudioIllustID, + StudioDesc: sqlc_title.StudioDesc, + StudioStorageType: sqlc_title.StudioStorageType, + StudioImagePath: sqlc_title.StudioImagePath, + } } return oapi.GetUsersUserIdTitles200JSONResponse(userTitles), nil diff --git a/modules/backend/queries.sql b/modules/backend/queries.sql index 307eb4f..ee2a84a 100644 --- a/modules/backend/queries.sql +++ b/modules/backend/queries.sql @@ -95,7 +95,7 @@ LEFT JOIN tags as g ON (tt.tag_id = g.id) LEFT JOIN studios as s ON (t.studio_id = s.id) LEFT JOIN images as si ON (s.illust_id = si.id) -WHERE id = sqlc.arg('title_id')::bigint +WHERE t.id = sqlc.arg('title_id')::bigint GROUP BY t.id, i.id, s.id, si.id; @@ -187,7 +187,13 @@ WHERE END ) - AND (t.title_status::text IN (sqlc.arg('ongoing')::text, sqlc.arg('finished')::text, sqlc.arg('planned')::text)) + AND ( + -- Если массив пуст (NULL или []) — не фильтруем + cardinality(sqlc.arg('title_statuses')::text[]) = 0 + OR + -- Иначе: статус есть в списке + t.title_status = ANY(sqlc.arg('title_statuses')::text[]) +) AND (sqlc.narg('rating')::float IS NULL OR t.rating >= sqlc.narg('rating')::float) AND (sqlc.narg('release_year')::int IS NULL OR t.release_year = sqlc.narg('release_year')::int) AND (sqlc.narg('release_season')::release_season_t IS NULL OR t.release_season = sqlc.narg('release_season')::release_season_t) diff --git a/sql/queries.sql.go b/sql/queries.sql.go index d4fb7a6..bf2f08a 100644 --- a/sql/queries.sql.go +++ b/sql/queries.sql.go @@ -138,7 +138,7 @@ LEFT JOIN tags as g ON (tt.tag_id = g.id) LEFT JOIN studios as s ON (t.studio_id = s.id) LEFT JOIN images as si ON (s.illust_id = si.id) -WHERE id = $1::bigint +WHERE t.id = $1::bigint GROUP BY t.id, i.id, s.id, si.id ` @@ -428,10 +428,16 @@ WHERE END ) - AND (t.title_status::text IN ($7::text, $8::text, $9::text)) - AND ($10::float IS NULL OR t.rating >= $10::float) - AND ($11::int IS NULL OR t.release_year = $11::int) - AND ($12::release_season_t IS NULL OR t.release_season = $12::release_season_t) + AND ( + -- Если массив пуст (NULL или []) — не фильтруем + cardinality($7::text[]) = 0 + OR + -- Иначе: статус есть в списке + t.title_status = ANY($7::text[]) +) + AND ($8::float IS NULL OR t.rating >= $8::float) + AND ($9::int IS NULL OR t.release_year = $9::int) + AND ($10::release_season_t IS NULL OR t.release_season = $10::release_season_t) GROUP BY t.id, i.id, s.id, si.id @@ -454,7 +460,7 @@ ORDER BY CASE WHEN $2::text <> 'id' THEN t.id END ASC -LIMIT COALESCE($13::int, 100) +LIMIT COALESCE($11::int, 100) ` type SearchTitlesParams struct { @@ -464,9 +470,7 @@ type SearchTitlesParams struct { CursorID *int64 `json:"cursor_id"` CursorRating *float64 `json:"cursor_rating"` Word *string `json:"word"` - Ongoing string `json:"ongoing"` - Finished string `json:"finished"` - Planned string `json:"planned"` + TitleStatuses []string `json:"title_statuses"` Rating *float64 `json:"rating"` ReleaseYear *int32 `json:"release_year"` ReleaseSeason *ReleaseSeasonT `json:"release_season"` @@ -505,9 +509,7 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]S arg.CursorID, arg.CursorRating, arg.Word, - arg.Ongoing, - arg.Finished, - arg.Planned, + arg.TitleStatuses, arg.Rating, arg.ReleaseYear, arg.ReleaseSeason, @@ -564,7 +566,7 @@ SELECT u.ctime as user_ctime, i.storage_type::text as title_storage_type, i.image_path as title_image_path, - jsonb_agg_strict(g.tag_name)'[]'::jsonb as tag_names, + jsonb_agg(g.tag_name)'[]'::jsonb as tag_names, s.studio_name as studio_name, s.illust_id as studio_illust_id, s.studio_desc as studio_desc, @@ -718,7 +720,7 @@ type SearchUserTitlesRow struct { UserCtime pgtype.Timestamptz `json:"user_ctime"` TitleStorageType string `json:"title_storage_type"` TitleImagePath *string `json:"title_image_path"` - TagNames []byte `json:"tag_names"` + TagNames json.RawMessage `json:"tag_names"` StudioName *string `json:"studio_name"` StudioIllustID *int64 `json:"studio_illust_id"` StudioDesc *string `json:"studio_desc"`