feat: cursor implemented
This commit is contained in:
parent
9c0fada00e
commit
af0492cdf1
8 changed files with 435 additions and 106 deletions
|
|
@ -179,7 +179,7 @@ func (q *Queries) GetTitleTags(ctx context.Context, titleID int64) ([][]byte, er
|
|||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items [][]byte
|
||||
items := [][]byte{}
|
||||
for rows.Next() {
|
||||
var tag_names []byte
|
||||
if err := rows.Scan(&tag_names); err != nil {
|
||||
|
|
@ -289,84 +289,131 @@ const searchTitles = `-- name: SearchTitles :many
|
|||
SELECT
|
||||
id, title_names, studio_id, poster_id, title_status, rating, rating_count, release_year, release_season, season, episodes_aired, episodes_all, episodes_len
|
||||
FROM titles
|
||||
WHERE
|
||||
CASE
|
||||
WHEN $1::text IS NOT NULL THEN
|
||||
(
|
||||
SELECT bool_and(
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM jsonb_each_text(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
|
||||
WHERE
|
||||
CASE
|
||||
WHEN $1::boolean THEN
|
||||
-- forward: greater than cursor (next page)
|
||||
CASE $2::text
|
||||
WHEN 'year' THEN
|
||||
($3::int IS NULL) OR
|
||||
(release_year > $3::int) OR
|
||||
(release_year = $3::int AND id > $4::bigint)
|
||||
|
||||
WHEN 'rating' THEN
|
||||
($5::float IS NULL) OR
|
||||
(rating > $5::float) OR
|
||||
(rating = $5::float AND id > $4::bigint)
|
||||
|
||||
WHEN 'id' THEN
|
||||
($4::bigint IS NULL) OR
|
||||
(id > $4::bigint)
|
||||
|
||||
ELSE true -- fallback
|
||||
END
|
||||
|
||||
ELSE
|
||||
-- backward: less than cursor (prev page)
|
||||
CASE $2::text
|
||||
WHEN 'year' THEN
|
||||
($3::int IS NULL) OR
|
||||
(release_year < $3::int) OR
|
||||
(release_year = $3::int AND id < $4::bigint)
|
||||
|
||||
WHEN 'rating' THEN
|
||||
($5::float IS NULL) OR
|
||||
(rating < $5::float) OR
|
||||
(rating = $5::float AND id < $4::bigint)
|
||||
|
||||
WHEN 'id' THEN
|
||||
($4::bigint IS NULL) OR
|
||||
(id < $4::bigint)
|
||||
|
||||
ELSE true
|
||||
END
|
||||
END
|
||||
|
||||
AND ($2::title_status_t IS NULL OR title_status = $2::title_status_t)
|
||||
AND ($3::float IS NULL OR rating >= $3::float)
|
||||
AND ($4::int IS NULL OR release_year = $4::int)
|
||||
AND ($5::release_season_t IS NULL OR release_season = $5::release_season_t)
|
||||
ORDER BY
|
||||
-- Основной ключ: выбранное поле
|
||||
CASE
|
||||
WHEN $6::boolean AND $7::text = 'id' THEN id
|
||||
WHEN $6::boolean AND $7::text = 'year' THEN release_year
|
||||
WHEN $6::boolean AND $7::text = 'rating' THEN rating
|
||||
-- WHEN sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'views' THEN views
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN NOT $6::boolean AND $7::text = 'id' THEN id
|
||||
WHEN NOT $6::boolean AND $7::text = 'year' THEN release_year
|
||||
WHEN NOT $6::boolean AND $7::text = 'rating' THEN rating
|
||||
-- WHEN NOT sqlc.arg(forward)::boolean AND sqlc.arg(sort_by)::text = 'views' THEN views
|
||||
END DESC,
|
||||
AND (
|
||||
CASE
|
||||
WHEN $6::text IS NOT NULL THEN
|
||||
(
|
||||
SELECT bool_and(
|
||||
EXISTS (
|
||||
SELECT 1
|
||||
FROM jsonb_each_text(title_names) AS t(key, val)
|
||||
WHERE val ILIKE pattern
|
||||
)
|
||||
)
|
||||
FROM unnest(
|
||||
ARRAY(
|
||||
SELECT '%' || trim(w) || '%'
|
||||
FROM unnest(string_to_array($6::text, ' ')) AS w
|
||||
WHERE trim(w) <> ''
|
||||
)
|
||||
) AS pattern
|
||||
)
|
||||
ELSE true
|
||||
END
|
||||
)
|
||||
|
||||
-- Вторичный ключ: id — только если НЕ сортируем по id
|
||||
CASE
|
||||
WHEN $7::text != 'id' AND $6::boolean THEN id
|
||||
END ASC,
|
||||
CASE
|
||||
WHEN $7::text != 'id' AND NOT $6::boolean THEN id
|
||||
END DESC
|
||||
LIMIT COALESCE($8::int, 100)
|
||||
AND ($7::title_status_t IS NULL OR title_status = $7::title_status_t)
|
||||
AND ($8::float IS NULL OR rating >= $8::float)
|
||||
AND ($9::int IS NULL OR release_year = $9::int)
|
||||
AND ($10::release_season_t IS NULL OR release_season = $10::release_season_t)
|
||||
|
||||
ORDER BY
|
||||
CASE WHEN $1::boolean THEN
|
||||
CASE
|
||||
WHEN $2::text = 'id' THEN id
|
||||
WHEN $2::text = 'year' THEN release_year
|
||||
WHEN $2::text = 'rating' THEN rating
|
||||
END
|
||||
END ASC,
|
||||
CASE WHEN NOT $1::boolean THEN
|
||||
CASE
|
||||
WHEN $2::text = 'id' THEN id
|
||||
WHEN $2::text = 'year' THEN release_year
|
||||
WHEN $2::text = 'rating' THEN rating
|
||||
END
|
||||
END DESC,
|
||||
|
||||
CASE WHEN $2::text <> 'id' THEN id END ASC
|
||||
|
||||
LIMIT COALESCE($11::int, 100)
|
||||
`
|
||||
|
||||
type SearchTitlesParams struct {
|
||||
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"`
|
||||
Status *TitleStatusT `json:"status"`
|
||||
Rating *float64 `json:"rating"`
|
||||
ReleaseYear *int32 `json:"release_year"`
|
||||
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
||||
Forward bool `json:"forward"`
|
||||
SortBy string `json:"sort_by"`
|
||||
Limit *int32 `json:"limit"`
|
||||
}
|
||||
|
||||
func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]Title, error) {
|
||||
rows, err := q.db.Query(ctx, searchTitles,
|
||||
arg.Forward,
|
||||
arg.SortBy,
|
||||
arg.CursorYear,
|
||||
arg.CursorID,
|
||||
arg.CursorRating,
|
||||
arg.Word,
|
||||
arg.Status,
|
||||
arg.Rating,
|
||||
arg.ReleaseYear,
|
||||
arg.ReleaseSeason,
|
||||
arg.Forward,
|
||||
arg.SortBy,
|
||||
arg.Limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Title
|
||||
items := []Title{}
|
||||
for rows.Next() {
|
||||
var i Title
|
||||
if err := rows.Scan(
|
||||
|
|
@ -464,7 +511,6 @@ type SearchUserTitlesRow struct {
|
|||
}
|
||||
|
||||
// 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,
|
||||
|
|
@ -479,7 +525,7 @@ func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesPara
|
|||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []SearchUserTitlesRow
|
||||
items := []SearchUserTitlesRow{}
|
||||
for rows.Next() {
|
||||
var i SearchUserTitlesRow
|
||||
if err := rows.Scan(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ sql:
|
|||
sql_driver: "github.com/jackc/pgx/v5"
|
||||
emit_json_tags: true
|
||||
emit_pointers_for_null_types: true
|
||||
emit_empty_slices: true #slices returned by :many queries will be empty instead of nil
|
||||
overrides:
|
||||
- db_type: "uuid"
|
||||
nullable: false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue