feat: cursor stub added
This commit is contained in:
parent
fbf3f1d3a2
commit
34d9341e75
5 changed files with 214 additions and 20 deletions
|
|
@ -218,6 +218,9 @@ func (s Server) GetTitlesTitleId(ctx context.Context, request oapi.GetTitlesTitl
|
||||||
|
|
||||||
func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObject) (oapi.GetTitlesResponseObject, error) {
|
func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObject) (oapi.GetTitlesResponseObject, error) {
|
||||||
opai_titles := make([]oapi.Title, 0)
|
opai_titles := make([]oapi.Title, 0)
|
||||||
|
cursor := oapi.CursorObj{
|
||||||
|
Id: 1,
|
||||||
|
}
|
||||||
|
|
||||||
word := Word2Sqlc(request.Params.Word)
|
word := Word2Sqlc(request.Params.Word)
|
||||||
status, err := TitleStatus2Sqlc(request.Params.Status)
|
status, err := TitleStatus2Sqlc(request.Params.Status)
|
||||||
|
|
@ -237,7 +240,6 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje
|
||||||
Rating: request.Params.Rating,
|
Rating: request.Params.Rating,
|
||||||
ReleaseYear: request.Params.ReleaseYear,
|
ReleaseYear: request.Params.ReleaseYear,
|
||||||
ReleaseSeason: season,
|
ReleaseSeason: season,
|
||||||
Offset: request.Params.Offset,
|
|
||||||
Limit: request.Params.Limit,
|
Limit: request.Params.Limit,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -258,5 +260,5 @@ func (s Server) GetTitles(ctx context.Context, request oapi.GetTitlesRequestObje
|
||||||
opai_titles = append(opai_titles, t)
|
opai_titles = append(opai_titles, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
return oapi.GetTitles200JSONResponse(opai_titles), nil
|
return oapi.GetTitles200JSONResponse{Cursor: cursor, Data: opai_titles}, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,67 @@ WHERE
|
||||||
AND (sqlc.narg('rating')::float IS NULL OR rating >= sqlc.narg('rating')::float)
|
AND (sqlc.narg('rating')::float IS NULL OR rating >= sqlc.narg('rating')::float)
|
||||||
AND (sqlc.narg('release_year')::int IS NULL OR release_year = sqlc.narg('release_year')::int)
|
AND (sqlc.narg('release_year')::int IS NULL OR release_year = sqlc.narg('release_year')::int)
|
||||||
AND (sqlc.narg('release_season')::release_season_t IS NULL OR release_season = sqlc.narg('release_season')::release_season_t)
|
AND (sqlc.narg('release_season')::release_season_t IS NULL OR release_season = sqlc.narg('release_season')::release_season_t)
|
||||||
|
ORDER BY
|
||||||
|
-- Основной ключ: выбранное поле
|
||||||
|
CASE
|
||||||
|
WHEN sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'id' THEN id
|
||||||
|
WHEN sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'name' THEN name
|
||||||
|
WHEN sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'year' THEN release_year
|
||||||
|
WHEN sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'rating' THEN rating
|
||||||
|
WHEN sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'views' THEN views
|
||||||
|
END ASC,
|
||||||
|
CASE
|
||||||
|
WHEN NOT sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'id' THEN id
|
||||||
|
WHEN NOT sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'name' THEN name
|
||||||
|
WHEN NOT sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'year' THEN release_year
|
||||||
|
WHEN NOT sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'rating' THEN rating
|
||||||
|
WHEN NOT sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'views' THEN views
|
||||||
|
END DESC,
|
||||||
|
|
||||||
LIMIT COALESCE(sqlc.narg('limit')::int, 100) -- 100 is default limit
|
-- Вторичный ключ: id — только если НЕ сортируем по id
|
||||||
OFFSET sqlc.narg('offset')::int;
|
CASE
|
||||||
|
WHEN sqlc.arg(sort_by)::text != 'id' AND sqlc.arg(forward)::boolean THEN id
|
||||||
|
END ASC,
|
||||||
|
CASE
|
||||||
|
WHEN sqlc.arg(sort_by)::text != 'id' AND NOT sqlc.arg(forward)::boolean THEN id
|
||||||
|
END DESC
|
||||||
|
LIMIT COALESCE(sqlc.narg('limit')::int, 100); -- 100 is default limit
|
||||||
|
-- OFFSET sqlc.narg('offset')::int;
|
||||||
|
|
||||||
|
-- name: SearchUserTitles :many
|
||||||
|
SELECT
|
||||||
|
*
|
||||||
|
FROM usertitles as u
|
||||||
|
JOIN titles as t ON (u.title_id = t.id)
|
||||||
|
WHERE
|
||||||
|
CASE
|
||||||
|
WHEN sqlc.narg('word')::text IS NOT NULL THEN
|
||||||
|
(
|
||||||
|
SELECT bool_and(
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM jsonb_each_text(t.title_names) AS t(key, val)
|
||||||
|
WHERE val ILIKE pattern
|
||||||
|
)
|
||||||
|
)
|
||||||
|
FROM unnest(
|
||||||
|
ARRAY(
|
||||||
|
SELECT '%' || trim(w) || '%'
|
||||||
|
FROM unnest(string_to_array(sqlc.narg('word')::text, ' ')) AS w
|
||||||
|
WHERE trim(w) <> ''
|
||||||
|
)
|
||||||
|
) AS pattern
|
||||||
|
)
|
||||||
|
ELSE true
|
||||||
|
END
|
||||||
|
|
||||||
|
AND (sqlc.narg('status')::title_status_t IS NULL OR t.title_status = sqlc.narg('status')::title_status_t)
|
||||||
|
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)
|
||||||
|
AND (sqlc.narg('usertitle_status')::usertitle_status_t IS NULL OR u.usertitle_status = sqlc.narg('usertitle_status')::usertitle_status_t)
|
||||||
|
|
||||||
|
LIMIT COALESCE(sqlc.narg('limit')::int, 100); -- 100 is default limit
|
||||||
|
|
||||||
-- -- name: ListTitles :many
|
-- -- name: ListTitles :many
|
||||||
-- SELECT title_id, title_names, studio_id, poster_id, signal_ids,
|
-- SELECT title_id, title_names, studio_id, poster_id, signal_ids,
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ CREATE TABLE studios (
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE titles (
|
CREATE TABLE titles (
|
||||||
// TODO: anime type (film, season etc)
|
-- // TODO: anime type (film, season etc)
|
||||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||||
-- example {"ru": ["Атака титанов", "Атака Титанов"],"en": ["Attack on Titan", "AoT"],"ja": ["進撃の巨人", "しんげきのきょじん"]}
|
-- example {"ru": ["Атака титанов", "Атака Титанов"],"en": ["Attack on Titan", "AoT"],"ja": ["進撃の巨人", "しんげきのきょじん"]}
|
||||||
title_names jsonb NOT NULL,
|
title_names jsonb NOT NULL,
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,6 @@ type Review struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Data string `json:"data"`
|
Data string `json:"data"`
|
||||||
Rating *int32 `json:"rating"`
|
Rating *int32 `json:"rating"`
|
||||||
IllustID *int64 `json:"illust_id"`
|
|
||||||
UserID *int64 `json:"user_id"`
|
UserID *int64 `json:"user_id"`
|
||||||
TitleID *int64 `json:"title_id"`
|
TitleID *int64 `json:"title_id"`
|
||||||
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
CreatedAt pgtype.Timestamptz `json:"created_at"`
|
||||||
|
|
@ -277,10 +276,10 @@ type User struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Usertitle struct {
|
type Usertitle struct {
|
||||||
UserID int64 `json:"user_id"`
|
UserID int64 `json:"user_id"`
|
||||||
TitleID int64 `json:"title_id"`
|
TitleID int64 `json:"title_id"`
|
||||||
Status UsertitleStatusT `json:"status"`
|
Status UsertitleStatusT `json:"status"`
|
||||||
Rate *int32 `json:"rate"`
|
Rate *int32 `json:"rate"`
|
||||||
ReviewText *string `json:"review_text"`
|
ReviewID *int64 `json:"review_id"`
|
||||||
ReviewDate pgtype.Timestamptz `json:"review_date"`
|
Ctime pgtype.Timestamptz `json:"ctime"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ package sqlc
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
const createImage = `-- name: CreateImage :one
|
const createImage = `-- name: CreateImage :one
|
||||||
|
|
@ -31,7 +33,7 @@ func (q *Queries) CreateImage(ctx context.Context, arg CreateImageParams) (Image
|
||||||
const getImageByID = `-- name: GetImageByID :one
|
const getImageByID = `-- name: GetImageByID :one
|
||||||
SELECT id, storage_type, image_path
|
SELECT id, storage_type, image_path
|
||||||
FROM images
|
FROM images
|
||||||
WHERE id = $1
|
WHERE id = $1::bigint
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) GetImageByID(ctx context.Context, illustID int64) (Image, error) {
|
func (q *Queries) GetImageByID(ctx context.Context, illustID int64) (Image, error) {
|
||||||
|
|
@ -44,11 +46,13 @@ func (q *Queries) GetImageByID(ctx context.Context, illustID int64) (Image, erro
|
||||||
const getReviewByID = `-- name: GetReviewByID :one
|
const getReviewByID = `-- name: GetReviewByID :one
|
||||||
|
|
||||||
|
|
||||||
SELECT id, data, rating, illust_id, user_id, title_id, created_at
|
|
||||||
|
SELECT id, data, rating, user_id, title_id, created_at
|
||||||
FROM reviews
|
FROM reviews
|
||||||
WHERE review_id = $1::bigint
|
WHERE review_id = $1::bigint
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// 100 is default limit
|
||||||
// -- name: ListTitles :many
|
// -- name: ListTitles :many
|
||||||
// SELECT title_id, title_names, studio_id, poster_id, signal_ids,
|
// SELECT title_id, title_names, studio_id, poster_id, signal_ids,
|
||||||
//
|
//
|
||||||
|
|
@ -82,7 +86,6 @@ func (q *Queries) GetReviewByID(ctx context.Context, reviewID int64) (Review, er
|
||||||
&i.ID,
|
&i.ID,
|
||||||
&i.Data,
|
&i.Data,
|
||||||
&i.Rating,
|
&i.Rating,
|
||||||
&i.IllustID,
|
|
||||||
&i.UserID,
|
&i.UserID,
|
||||||
&i.TitleID,
|
&i.TitleID,
|
||||||
&i.CreatedAt,
|
&i.CreatedAt,
|
||||||
|
|
@ -312,9 +315,18 @@ WHERE
|
||||||
AND ($3::float IS NULL OR rating >= $3::float)
|
AND ($3::float IS NULL OR rating >= $3::float)
|
||||||
AND ($4::int IS NULL OR release_year = $4::int)
|
AND ($4::int IS NULL OR release_year = $4::int)
|
||||||
AND ($5::release_season_t IS NULL OR release_season = $5::release_season_t)
|
AND ($5::release_season_t IS NULL OR release_season = $5::release_season_t)
|
||||||
|
ORDER BY CASE
|
||||||
LIMIT COALESCE($7::int, 100) -- 100 is default limit
|
WHEN $6::boolean AND $7::text = 'name' THEN name
|
||||||
OFFSET $6::int
|
WHEN $8::boolean AND $7::text = 'id' THEN id
|
||||||
|
WHEN $8::boolean AND $7::text = 'name' THEN name
|
||||||
|
WHEN $8::boolean AND $7::text = 'id' THEN id
|
||||||
|
END ASC, CASE
|
||||||
|
WHEN NOT $8::boolean AND $7::text = 'name' THEN name
|
||||||
|
WHEN NOT $8::boolean AND $7::text = 'id' THEN id
|
||||||
|
WHEN NOT $8::boolean AND $7::text = 'name' THEN name
|
||||||
|
WHEN NOT $8::boolean AND $7::text = 'id' THEN id
|
||||||
|
END DESC
|
||||||
|
LIMIT COALESCE($9::int, 100)
|
||||||
`
|
`
|
||||||
|
|
||||||
type SearchTitlesParams struct {
|
type SearchTitlesParams struct {
|
||||||
|
|
@ -323,7 +335,9 @@ type SearchTitlesParams struct {
|
||||||
Rating *float64 `json:"rating"`
|
Rating *float64 `json:"rating"`
|
||||||
ReleaseYear *int32 `json:"release_year"`
|
ReleaseYear *int32 `json:"release_year"`
|
||||||
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
||||||
Offset *int32 `json:"offset"`
|
Forward bool `json:"forward"`
|
||||||
|
OrderBy string `json:"order_by"`
|
||||||
|
Reverse bool `json:"reverse"`
|
||||||
Limit *int32 `json:"limit"`
|
Limit *int32 `json:"limit"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -334,7 +348,9 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]T
|
||||||
arg.Rating,
|
arg.Rating,
|
||||||
arg.ReleaseYear,
|
arg.ReleaseYear,
|
||||||
arg.ReleaseSeason,
|
arg.ReleaseSeason,
|
||||||
arg.Offset,
|
arg.Forward,
|
||||||
|
arg.OrderBy,
|
||||||
|
arg.Reverse,
|
||||||
arg.Limit,
|
arg.Limit,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -368,3 +384,122 @@ func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]T
|
||||||
}
|
}
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const searchUserTitles = `-- name: SearchUserTitles :many
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
user_id, title_id, status, rate, review_id, ctime, id, title_names, studio_id, poster_id, title_status, rating, rating_count, release_year, release_season, season, episodes_aired, episodes_all, episodes_len
|
||||||
|
FROM usertitles as u
|
||||||
|
JOIN titles as t ON (u.title_id = t.id)
|
||||||
|
WHERE
|
||||||
|
CASE
|
||||||
|
WHEN $1::text IS NOT NULL THEN
|
||||||
|
(
|
||||||
|
SELECT bool_and(
|
||||||
|
EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM jsonb_each_text(t.title_names) AS t(key, val)
|
||||||
|
WHERE val ILIKE pattern
|
||||||
|
)
|
||||||
|
)
|
||||||
|
FROM unnest(
|
||||||
|
ARRAY(
|
||||||
|
SELECT '%' || trim(w) || '%'
|
||||||
|
FROM unnest(string_to_array($1::text, ' ')) AS w
|
||||||
|
WHERE trim(w) <> ''
|
||||||
|
)
|
||||||
|
) AS pattern
|
||||||
|
)
|
||||||
|
ELSE true
|
||||||
|
END
|
||||||
|
|
||||||
|
AND ($2::title_status_t IS NULL OR t.title_status = $2::title_status_t)
|
||||||
|
AND ($3::float IS NULL OR t.rating >= $3::float)
|
||||||
|
AND ($4::int IS NULL OR t.release_year = $4::int)
|
||||||
|
AND ($5::release_season_t IS NULL OR t.release_season = $5::release_season_t)
|
||||||
|
AND ($6::usertitle_status_t IS NULL OR u.usertitle_status = $6::usertitle_status_t)
|
||||||
|
|
||||||
|
LIMIT COALESCE($7::int, 100)
|
||||||
|
`
|
||||||
|
|
||||||
|
type SearchUserTitlesParams struct {
|
||||||
|
Word *string `json:"word"`
|
||||||
|
Status *TitleStatusT `json:"status"`
|
||||||
|
Rating *float64 `json:"rating"`
|
||||||
|
ReleaseYear *int32 `json:"release_year"`
|
||||||
|
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
||||||
|
UsertitleStatus NullUsertitleStatusT `json:"usertitle_status"`
|
||||||
|
Limit *int32 `json:"limit"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SearchUserTitlesRow struct {
|
||||||
|
UserID int64 `json:"user_id"`
|
||||||
|
TitleID int64 `json:"title_id"`
|
||||||
|
Status UsertitleStatusT `json:"status"`
|
||||||
|
Rate *int32 `json:"rate"`
|
||||||
|
ReviewID *int64 `json:"review_id"`
|
||||||
|
Ctime pgtype.Timestamptz `json:"ctime"`
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
TitleNames []byte `json:"title_names"`
|
||||||
|
StudioID int64 `json:"studio_id"`
|
||||||
|
PosterID *int64 `json:"poster_id"`
|
||||||
|
TitleStatus TitleStatusT `json:"title_status"`
|
||||||
|
Rating *float64 `json:"rating"`
|
||||||
|
RatingCount *int32 `json:"rating_count"`
|
||||||
|
ReleaseYear *int32 `json:"release_year"`
|
||||||
|
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
||||||
|
Season *int32 `json:"season"`
|
||||||
|
EpisodesAired *int32 `json:"episodes_aired"`
|
||||||
|
EpisodesAll *int32 `json:"episodes_all"`
|
||||||
|
EpisodesLen []byte `json:"episodes_len"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 100 is default limit
|
||||||
|
// OFFSET sqlc.narg('offset')::int;
|
||||||
|
func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesParams) ([]SearchUserTitlesRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, searchUserTitles,
|
||||||
|
arg.Word,
|
||||||
|
arg.Status,
|
||||||
|
arg.Rating,
|
||||||
|
arg.ReleaseYear,
|
||||||
|
arg.ReleaseSeason,
|
||||||
|
arg.UsertitleStatus,
|
||||||
|
arg.Limit,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []SearchUserTitlesRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i SearchUserTitlesRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.UserID,
|
||||||
|
&i.TitleID,
|
||||||
|
&i.Status,
|
||||||
|
&i.Rate,
|
||||||
|
&i.ReviewID,
|
||||||
|
&i.Ctime,
|
||||||
|
&i.ID,
|
||||||
|
&i.TitleNames,
|
||||||
|
&i.StudioID,
|
||||||
|
&i.PosterID,
|
||||||
|
&i.TitleStatus,
|
||||||
|
&i.Rating,
|
||||||
|
&i.RatingCount,
|
||||||
|
&i.ReleaseYear,
|
||||||
|
&i.ReleaseSeason,
|
||||||
|
&i.Season,
|
||||||
|
&i.EpisodesAired,
|
||||||
|
&i.EpisodesAll,
|
||||||
|
&i.EpisodesLen,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue