1001 lines
30 KiB
Go
1001 lines
30 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: queries.sql
|
|
|
|
package sqlc
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
)
|
|
|
|
const createImage = `-- name: CreateImage :one
|
|
INSERT INTO images (storage_type, image_path)
|
|
VALUES ($1, $2)
|
|
RETURNING id, storage_type, image_path
|
|
`
|
|
|
|
type CreateImageParams struct {
|
|
StorageType StorageTypeT `json:"storage_type"`
|
|
ImagePath string `json:"image_path"`
|
|
}
|
|
|
|
func (q *Queries) CreateImage(ctx context.Context, arg CreateImageParams) (Image, error) {
|
|
row := q.db.QueryRow(ctx, createImage, arg.StorageType, arg.ImagePath)
|
|
var i Image
|
|
err := row.Scan(&i.ID, &i.StorageType, &i.ImagePath)
|
|
return i, err
|
|
}
|
|
|
|
const deleteUserTitle = `-- name: DeleteUserTitle :one
|
|
DELETE FROM usertitles
|
|
WHERE user_id = $1
|
|
AND title_id = $2
|
|
RETURNING user_id, title_id, status, rate, review_id, ctime
|
|
`
|
|
|
|
type DeleteUserTitleParams struct {
|
|
UserID int64 `json:"user_id"`
|
|
TitleID int64 `json:"title_id"`
|
|
}
|
|
|
|
func (q *Queries) DeleteUserTitle(ctx context.Context, arg DeleteUserTitleParams) (Usertitle, error) {
|
|
row := q.db.QueryRow(ctx, deleteUserTitle, arg.UserID, arg.TitleID)
|
|
var i Usertitle
|
|
err := row.Scan(
|
|
&i.UserID,
|
|
&i.TitleID,
|
|
&i.Status,
|
|
&i.Rate,
|
|
&i.ReviewID,
|
|
&i.Ctime,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getImageByID = `-- name: GetImageByID :one
|
|
SELECT id, storage_type, image_path
|
|
FROM images
|
|
WHERE id = $1::bigint
|
|
`
|
|
|
|
func (q *Queries) GetImageByID(ctx context.Context, illustID int64) (Image, error) {
|
|
row := q.db.QueryRow(ctx, getImageByID, illustID)
|
|
var i Image
|
|
err := row.Scan(&i.ID, &i.StorageType, &i.ImagePath)
|
|
return i, err
|
|
}
|
|
|
|
const getReviewByID = `-- name: GetReviewByID :one
|
|
|
|
SELECT id, data, rating, user_id, title_id, created_at
|
|
FROM reviews
|
|
WHERE review_id = $1::bigint
|
|
`
|
|
|
|
// 100 is default limit
|
|
func (q *Queries) GetReviewByID(ctx context.Context, reviewID int64) (Review, error) {
|
|
row := q.db.QueryRow(ctx, getReviewByID, reviewID)
|
|
var i Review
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Data,
|
|
&i.Rating,
|
|
&i.UserID,
|
|
&i.TitleID,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getStudioByID = `-- name: GetStudioByID :one
|
|
SELECT id, studio_name, illust_id, studio_desc
|
|
FROM studios
|
|
WHERE id = $1::bigint
|
|
`
|
|
|
|
func (q *Queries) GetStudioByID(ctx context.Context, studioID int64) (Studio, error) {
|
|
row := q.db.QueryRow(ctx, getStudioByID, studioID)
|
|
var i Studio
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.StudioName,
|
|
&i.IllustID,
|
|
&i.StudioDesc,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTitleByID = `-- name: GetTitleByID :one
|
|
SELECT
|
|
t.id, t.title_names, t.studio_id, t.poster_id, t.title_status, t.rating, t.rating_count, t.release_year, t.release_season, t.season, t.episodes_aired, t.episodes_all, t.episodes_len,
|
|
i.storage_type as title_storage_type,
|
|
i.image_path as title_image_path,
|
|
COALESCE(
|
|
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
|
|
'[]'::jsonb
|
|
)::jsonb as tag_names,
|
|
s.studio_name as studio_name,
|
|
s.illust_id as studio_illust_id,
|
|
s.studio_desc as studio_desc,
|
|
si.storage_type as studio_storage_type,
|
|
si.image_path as studio_image_path
|
|
|
|
FROM titles as t
|
|
LEFT JOIN images as i ON (t.poster_id = i.id)
|
|
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
|
|
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 t.id = $1::bigint
|
|
GROUP BY
|
|
t.id, i.id, s.id, si.id
|
|
`
|
|
|
|
type GetTitleByIDRow struct {
|
|
ID int64 `json:"id"`
|
|
TitleNames json.RawMessage `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"`
|
|
TitleStorageType *StorageTypeT `json:"title_storage_type"`
|
|
TitleImagePath *string `json:"title_image_path"`
|
|
TagNames json.RawMessage `json:"tag_names"`
|
|
StudioName *string `json:"studio_name"`
|
|
StudioIllustID *int64 `json:"studio_illust_id"`
|
|
StudioDesc *string `json:"studio_desc"`
|
|
StudioStorageType *StorageTypeT `json:"studio_storage_type"`
|
|
StudioImagePath *string `json:"studio_image_path"`
|
|
}
|
|
|
|
// sqlc.struct: TitlesFull
|
|
func (q *Queries) GetTitleByID(ctx context.Context, titleID int64) (GetTitleByIDRow, error) {
|
|
row := q.db.QueryRow(ctx, getTitleByID, titleID)
|
|
var i GetTitleByIDRow
|
|
err := row.Scan(
|
|
&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,
|
|
&i.TitleStorageType,
|
|
&i.TitleImagePath,
|
|
&i.TagNames,
|
|
&i.StudioName,
|
|
&i.StudioIllustID,
|
|
&i.StudioDesc,
|
|
&i.StudioStorageType,
|
|
&i.StudioImagePath,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTitleTags = `-- name: GetTitleTags :many
|
|
SELECT
|
|
tag_names
|
|
FROM tags as g
|
|
JOIN title_tags as t ON(t.tag_id = g.id)
|
|
WHERE t.title_id = $1::bigint
|
|
`
|
|
|
|
func (q *Queries) GetTitleTags(ctx context.Context, titleID int64) ([]json.RawMessage, error) {
|
|
rows, err := q.db.Query(ctx, getTitleTags, titleID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []json.RawMessage{}
|
|
for rows.Next() {
|
|
var tag_names json.RawMessage
|
|
if err := rows.Scan(&tag_names); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, tag_names)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const getUserByID = `-- name: GetUserByID :one
|
|
SELECT
|
|
t.id as id,
|
|
t.avatar_id as avatar_id,
|
|
t.mail as mail,
|
|
t.nickname as nickname,
|
|
t.disp_name as disp_name,
|
|
t.user_desc as user_desc,
|
|
t.creation_date as creation_date,
|
|
i.storage_type as storage_type,
|
|
i.image_path as image_path
|
|
FROM users as t
|
|
LEFT JOIN images as i ON (t.avatar_id = i.id)
|
|
WHERE t.id = $1::bigint
|
|
`
|
|
|
|
type GetUserByIDRow struct {
|
|
ID int64 `json:"id"`
|
|
AvatarID *int64 `json:"avatar_id"`
|
|
Mail *string `json:"mail"`
|
|
Nickname string `json:"nickname"`
|
|
DispName *string `json:"disp_name"`
|
|
UserDesc *string `json:"user_desc"`
|
|
CreationDate time.Time `json:"creation_date"`
|
|
StorageType *StorageTypeT `json:"storage_type"`
|
|
ImagePath *string `json:"image_path"`
|
|
}
|
|
|
|
func (q *Queries) GetUserByID(ctx context.Context, id int64) (GetUserByIDRow, error) {
|
|
row := q.db.QueryRow(ctx, getUserByID, id)
|
|
var i GetUserByIDRow
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.AvatarID,
|
|
&i.Mail,
|
|
&i.Nickname,
|
|
&i.DispName,
|
|
&i.UserDesc,
|
|
&i.CreationDate,
|
|
&i.StorageType,
|
|
&i.ImagePath,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getUserTitleByID = `-- name: GetUserTitleByID :one
|
|
SELECT
|
|
ut.user_id, ut.title_id, ut.status, ut.rate, ut.review_id, ut.ctime,
|
|
t.id, t.title_names, t.studio_id, t.poster_id, t.title_status, t.rating, t.rating_count, t.release_year, t.release_season, t.season, t.episodes_aired, t.episodes_all, t.episodes_len,
|
|
i.storage_type as title_storage_type,
|
|
i.image_path as title_image_path,
|
|
COALESCE(
|
|
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
|
|
'[]'::jsonb
|
|
)::jsonb as tag_names,
|
|
s.studio_name as studio_name,
|
|
s.illust_id as studio_illust_id,
|
|
s.studio_desc as studio_desc,
|
|
si.storage_type as studio_storage_type,
|
|
si.image_path as studio_image_path
|
|
|
|
FROM usertitles as ut
|
|
LEFT JOIN users as u ON (ut.user_id = u.id)
|
|
LEFT JOIN titles as t ON (ut.title_id = t.id)
|
|
LEFT JOIN images as i ON (t.poster_id = i.id)
|
|
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
|
|
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 t.id = $1::bigint AND u.id = $2::bigint
|
|
GROUP BY
|
|
t.id, i.id, s.id, si.id
|
|
`
|
|
|
|
type GetUserTitleByIDParams struct {
|
|
TitleID int64 `json:"title_id"`
|
|
UserID int64 `json:"user_id"`
|
|
}
|
|
|
|
type GetUserTitleByIDRow 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 time.Time `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"`
|
|
TitleStorageType *StorageTypeT `json:"title_storage_type"`
|
|
TitleImagePath *string `json:"title_image_path"`
|
|
TagNames json.RawMessage `json:"tag_names"`
|
|
StudioName *string `json:"studio_name"`
|
|
StudioIllustID *int64 `json:"studio_illust_id"`
|
|
StudioDesc *string `json:"studio_desc"`
|
|
StudioStorageType *StorageTypeT `json:"studio_storage_type"`
|
|
StudioImagePath *string `json:"studio_image_path"`
|
|
}
|
|
|
|
func (q *Queries) GetUserTitleByID(ctx context.Context, arg GetUserTitleByIDParams) (GetUserTitleByIDRow, error) {
|
|
row := q.db.QueryRow(ctx, getUserTitleByID, arg.TitleID, arg.UserID)
|
|
var i GetUserTitleByIDRow
|
|
err := row.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,
|
|
&i.TitleStorageType,
|
|
&i.TitleImagePath,
|
|
&i.TagNames,
|
|
&i.StudioName,
|
|
&i.StudioIllustID,
|
|
&i.StudioDesc,
|
|
&i.StudioStorageType,
|
|
&i.StudioImagePath,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const insertStudio = `-- name: InsertStudio :one
|
|
INSERT INTO studios (studio_name, illust_id, studio_desc)
|
|
VALUES (
|
|
$1::text,
|
|
$2::bigint,
|
|
$3::text)
|
|
RETURNING id, studio_name, illust_id, studio_desc
|
|
`
|
|
|
|
type InsertStudioParams struct {
|
|
StudioName string `json:"studio_name"`
|
|
IllustID *int64 `json:"illust_id"`
|
|
StudioDesc *string `json:"studio_desc"`
|
|
}
|
|
|
|
func (q *Queries) InsertStudio(ctx context.Context, arg InsertStudioParams) (Studio, error) {
|
|
row := q.db.QueryRow(ctx, insertStudio, arg.StudioName, arg.IllustID, arg.StudioDesc)
|
|
var i Studio
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.StudioName,
|
|
&i.IllustID,
|
|
&i.StudioDesc,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const insertTag = `-- name: InsertTag :one
|
|
INSERT INTO tags (tag_names)
|
|
VALUES (
|
|
$1::jsonb)
|
|
RETURNING id, tag_names
|
|
`
|
|
|
|
func (q *Queries) InsertTag(ctx context.Context, tagNames json.RawMessage) (Tag, error) {
|
|
row := q.db.QueryRow(ctx, insertTag, tagNames)
|
|
var i Tag
|
|
err := row.Scan(&i.ID, &i.TagNames)
|
|
return i, err
|
|
}
|
|
|
|
const insertTitleTags = `-- name: InsertTitleTags :one
|
|
INSERT INTO title_tags (title_id, tag_id)
|
|
VALUES (
|
|
$1::bigint,
|
|
$2::bigint)
|
|
RETURNING title_id, tag_id
|
|
`
|
|
|
|
type InsertTitleTagsParams struct {
|
|
TitleID int64 `json:"title_id"`
|
|
TagID int64 `json:"tag_id"`
|
|
}
|
|
|
|
func (q *Queries) InsertTitleTags(ctx context.Context, arg InsertTitleTagsParams) (TitleTag, error) {
|
|
row := q.db.QueryRow(ctx, insertTitleTags, arg.TitleID, arg.TagID)
|
|
var i TitleTag
|
|
err := row.Scan(&i.TitleID, &i.TagID)
|
|
return i, err
|
|
}
|
|
|
|
const insertUserTitle = `-- name: InsertUserTitle :one
|
|
INSERT INTO usertitles (user_id, title_id, status, rate, review_id)
|
|
VALUES (
|
|
$1::bigint,
|
|
$2::bigint,
|
|
$3::usertitle_status_t,
|
|
$4::int,
|
|
$5::bigint
|
|
)
|
|
RETURNING user_id, title_id, status, rate, review_id, ctime
|
|
`
|
|
|
|
type InsertUserTitleParams struct {
|
|
UserID int64 `json:"user_id"`
|
|
TitleID int64 `json:"title_id"`
|
|
Status UsertitleStatusT `json:"status"`
|
|
Rate *int32 `json:"rate"`
|
|
ReviewID *int64 `json:"review_id"`
|
|
}
|
|
|
|
func (q *Queries) InsertUserTitle(ctx context.Context, arg InsertUserTitleParams) (Usertitle, error) {
|
|
row := q.db.QueryRow(ctx, insertUserTitle,
|
|
arg.UserID,
|
|
arg.TitleID,
|
|
arg.Status,
|
|
arg.Rate,
|
|
arg.ReviewID,
|
|
)
|
|
var i Usertitle
|
|
err := row.Scan(
|
|
&i.UserID,
|
|
&i.TitleID,
|
|
&i.Status,
|
|
&i.Rate,
|
|
&i.ReviewID,
|
|
&i.Ctime,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const searchTitles = `-- name: SearchTitles :many
|
|
SELECT
|
|
t.id as id,
|
|
t.title_names as title_names,
|
|
t.poster_id as poster_id,
|
|
t.title_status as title_status,
|
|
t.rating as rating,
|
|
t.rating_count as rating_count,
|
|
t.release_year as release_year,
|
|
t.release_season as release_season,
|
|
t.season as season,
|
|
t.episodes_aired as episodes_aired,
|
|
t.episodes_all as episodes_all,
|
|
i.storage_type as title_storage_type,
|
|
i.image_path as title_image_path,
|
|
COALESCE(
|
|
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
|
|
'[]'::jsonb
|
|
)::jsonb as tag_names,
|
|
s.studio_name as studio_name
|
|
|
|
FROM titles as t
|
|
LEFT JOIN images as i ON (t.poster_id = i.id)
|
|
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
|
|
LEFT JOIN tags as g ON (tt.tag_id = g.id)
|
|
LEFT JOIN studios as s ON (t.studio_id = s.id)
|
|
|
|
WHERE
|
|
CASE
|
|
WHEN $1::boolean THEN
|
|
-- forward: greater than cursor (next page)
|
|
CASE $2::text
|
|
WHEN 'year' THEN
|
|
($3::int IS NULL) OR
|
|
(t.release_year > $3::int) OR
|
|
(t.release_year = $3::int AND t.id > $4::bigint)
|
|
|
|
WHEN 'rating' THEN
|
|
($5::float IS NULL) OR
|
|
(t.rating > $5::float) OR
|
|
(t.rating = $5::float AND t.id > $4::bigint)
|
|
|
|
WHEN 'id' THEN
|
|
($4::bigint IS NULL) OR
|
|
(t.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
|
|
(t.release_year < $3::int) OR
|
|
(t.release_year = $3::int AND t.id < $4::bigint)
|
|
|
|
WHEN 'rating' THEN
|
|
($5::float IS NULL) OR
|
|
(t.rating < $5::float) OR
|
|
(t.rating = $5::float AND t.id < $4::bigint)
|
|
|
|
WHEN 'id' THEN
|
|
($4::bigint IS NULL) OR
|
|
(t.id < $4::bigint)
|
|
|
|
ELSE true
|
|
END
|
|
END
|
|
|
|
AND (
|
|
CASE
|
|
WHEN $6::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($6::text, ' ')) AS w
|
|
WHERE trim(w) <> ''
|
|
)
|
|
) AS pattern
|
|
)
|
|
ELSE true
|
|
END
|
|
)
|
|
|
|
AND (
|
|
$7::title_status_t[] IS NULL
|
|
OR array_length($7::title_status_t[], 1) IS NULL
|
|
OR array_length($7::title_status_t[], 1) = 0
|
|
OR t.title_status = ANY($7::title_status_t[])
|
|
)
|
|
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
|
|
|
|
ORDER BY
|
|
CASE WHEN $1::boolean THEN
|
|
CASE
|
|
WHEN $2::text = 'id' THEN t.id
|
|
WHEN $2::text = 'year' THEN t.release_year
|
|
WHEN $2::text = 'rating' THEN t.rating
|
|
END
|
|
END ASC,
|
|
CASE WHEN NOT $1::boolean THEN
|
|
CASE
|
|
WHEN $2::text = 'id' THEN t.id
|
|
WHEN $2::text = 'year' THEN t.release_year
|
|
WHEN $2::text = 'rating' THEN t.rating
|
|
END
|
|
END DESC,
|
|
|
|
CASE WHEN $2::text <> 'id' THEN t.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"`
|
|
TitleStatuses []TitleStatusT `json:"title_statuses"`
|
|
Rating *float64 `json:"rating"`
|
|
ReleaseYear *int32 `json:"release_year"`
|
|
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
|
Limit *int32 `json:"limit"`
|
|
}
|
|
|
|
type SearchTitlesRow struct {
|
|
ID int64 `json:"id"`
|
|
TitleNames json.RawMessage `json:"title_names"`
|
|
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"`
|
|
TitleStorageType *StorageTypeT `json:"title_storage_type"`
|
|
TitleImagePath *string `json:"title_image_path"`
|
|
TagNames json.RawMessage `json:"tag_names"`
|
|
StudioName *string `json:"studio_name"`
|
|
}
|
|
|
|
func (q *Queries) SearchTitles(ctx context.Context, arg SearchTitlesParams) ([]SearchTitlesRow, error) {
|
|
rows, err := q.db.Query(ctx, searchTitles,
|
|
arg.Forward,
|
|
arg.SortBy,
|
|
arg.CursorYear,
|
|
arg.CursorID,
|
|
arg.CursorRating,
|
|
arg.Word,
|
|
arg.TitleStatuses,
|
|
arg.Rating,
|
|
arg.ReleaseYear,
|
|
arg.ReleaseSeason,
|
|
arg.Limit,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []SearchTitlesRow{}
|
|
for rows.Next() {
|
|
var i SearchTitlesRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.TitleNames,
|
|
&i.PosterID,
|
|
&i.TitleStatus,
|
|
&i.Rating,
|
|
&i.RatingCount,
|
|
&i.ReleaseYear,
|
|
&i.ReleaseSeason,
|
|
&i.Season,
|
|
&i.EpisodesAired,
|
|
&i.EpisodesAll,
|
|
&i.TitleStorageType,
|
|
&i.TitleImagePath,
|
|
&i.TagNames,
|
|
&i.StudioName,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const searchUserTitles = `-- name: SearchUserTitles :many
|
|
|
|
SELECT
|
|
t.id as id,
|
|
t.title_names as title_names,
|
|
t.poster_id as poster_id,
|
|
t.title_status as title_status,
|
|
t.rating as rating,
|
|
t.rating_count as rating_count,
|
|
t.release_year as release_year,
|
|
t.release_season as release_season,
|
|
t.season as season,
|
|
t.episodes_aired as episodes_aired,
|
|
t.episodes_all as episodes_all,
|
|
u.user_id as user_id,
|
|
u.status as usertitle_status,
|
|
u.rate as user_rate,
|
|
u.review_id as review_id,
|
|
u.ctime as user_ctime,
|
|
i.storage_type as title_storage_type,
|
|
i.image_path as title_image_path,
|
|
COALESCE(
|
|
jsonb_agg(g.tag_names) FILTER (WHERE g.tag_names IS NOT NULL),
|
|
'[]'::jsonb
|
|
)::jsonb as tag_names,
|
|
s.studio_name as studio_name
|
|
|
|
FROM usertitles as u
|
|
JOIN titles as t ON (u.title_id = t.id)
|
|
LEFT JOIN images as i ON (t.poster_id = i.id)
|
|
LEFT JOIN title_tags as tt ON (t.id = tt.title_id)
|
|
LEFT JOIN tags as g ON (tt.tag_id = g.id)
|
|
LEFT JOIN studios as s ON (t.studio_id = s.id)
|
|
|
|
WHERE
|
|
u.user_id = $1::bigint
|
|
AND
|
|
CASE
|
|
WHEN $2::boolean THEN
|
|
-- forward: greater than cursor (next page)
|
|
CASE $3::text
|
|
WHEN 'year' THEN
|
|
($4::int IS NULL) OR
|
|
(t.release_year > $4::int) OR
|
|
(t.release_year = $4::int AND t.id > $5::bigint)
|
|
|
|
WHEN 'rating' THEN
|
|
($6::float IS NULL) OR
|
|
(t.rating > $6::float) OR
|
|
(t.rating = $6::float AND t.id > $5::bigint)
|
|
|
|
WHEN 'id' THEN
|
|
($5::bigint IS NULL) OR
|
|
(t.id > $5::bigint)
|
|
|
|
ELSE true -- fallback
|
|
END
|
|
|
|
ELSE
|
|
-- backward: less than cursor (prev page)
|
|
CASE $3::text
|
|
WHEN 'year' THEN
|
|
($4::int IS NULL) OR
|
|
(t.release_year < $4::int) OR
|
|
(t.release_year = $4::int AND t.id < $5::bigint)
|
|
|
|
WHEN 'rating' THEN
|
|
($6::float IS NULL) OR
|
|
(t.rating < $6::float) OR
|
|
(t.rating = $6::float AND t.id < $5::bigint)
|
|
|
|
WHEN 'id' THEN
|
|
($5::bigint IS NULL) OR
|
|
(t.id < $5::bigint)
|
|
|
|
ELSE true
|
|
END
|
|
END
|
|
|
|
AND (
|
|
CASE
|
|
WHEN $7::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($7::text, ' ')) AS w
|
|
WHERE trim(w) <> ''
|
|
)
|
|
) AS pattern
|
|
)
|
|
ELSE true
|
|
END
|
|
)
|
|
|
|
AND (
|
|
$8::title_status_t[] IS NULL
|
|
OR array_length($8::title_status_t[], 1) IS NULL
|
|
OR array_length($8::title_status_t[], 1) = 0
|
|
OR t.title_status = ANY($8::title_status_t[])
|
|
)
|
|
AND (
|
|
$9::usertitle_status_t[] IS NULL
|
|
OR array_length($9::usertitle_status_t[], 1) IS NULL
|
|
OR array_length($9::usertitle_status_t[], 1) = 0
|
|
OR u.status = ANY($9::usertitle_status_t[])
|
|
)
|
|
AND ($10::int IS NULL OR u.rate >= $10::int)
|
|
AND ($11::float IS NULL OR t.rating >= $11::float)
|
|
AND ($12::int IS NULL OR t.release_year = $12::int)
|
|
AND ($13::release_season_t IS NULL OR t.release_season = $13::release_season_t)
|
|
|
|
GROUP BY
|
|
t.id, u.user_id, u.status, u.rate, u.review_id, u.ctime, i.id, s.id
|
|
|
|
ORDER BY
|
|
CASE WHEN $2::boolean THEN
|
|
CASE
|
|
WHEN $3::text = 'id' THEN t.id
|
|
WHEN $3::text = 'year' THEN t.release_year
|
|
WHEN $3::text = 'rating' THEN t.rating
|
|
WHEN $3::text = 'rate' THEN u.rate
|
|
END
|
|
END ASC,
|
|
CASE WHEN NOT $2::boolean THEN
|
|
CASE
|
|
WHEN $3::text = 'id' THEN t.id
|
|
WHEN $3::text = 'year' THEN t.release_year
|
|
WHEN $3::text = 'rating' THEN t.rating
|
|
WHEN $3::text = 'rate' THEN u.rate
|
|
END
|
|
END DESC,
|
|
|
|
CASE WHEN $3::text <> 'id' THEN t.id END ASC
|
|
|
|
LIMIT COALESCE($14::int, 100)
|
|
`
|
|
|
|
type SearchUserTitlesParams struct {
|
|
UserID int64 `json:"user_id"`
|
|
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"`
|
|
TitleStatuses []TitleStatusT `json:"title_statuses"`
|
|
UsertitleStatuses []UsertitleStatusT `json:"usertitle_statuses"`
|
|
Rate *int32 `json:"rate"`
|
|
Rating *float64 `json:"rating"`
|
|
ReleaseYear *int32 `json:"release_year"`
|
|
ReleaseSeason *ReleaseSeasonT `json:"release_season"`
|
|
Limit *int32 `json:"limit"`
|
|
}
|
|
|
|
type SearchUserTitlesRow struct {
|
|
ID int64 `json:"id"`
|
|
TitleNames json.RawMessage `json:"title_names"`
|
|
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"`
|
|
UserID int64 `json:"user_id"`
|
|
UsertitleStatus UsertitleStatusT `json:"usertitle_status"`
|
|
UserRate *int32 `json:"user_rate"`
|
|
ReviewID *int64 `json:"review_id"`
|
|
UserCtime time.Time `json:"user_ctime"`
|
|
TitleStorageType *StorageTypeT `json:"title_storage_type"`
|
|
TitleImagePath *string `json:"title_image_path"`
|
|
TagNames json.RawMessage `json:"tag_names"`
|
|
StudioName *string `json:"studio_name"`
|
|
}
|
|
|
|
// 100 is default limit
|
|
func (q *Queries) SearchUserTitles(ctx context.Context, arg SearchUserTitlesParams) ([]SearchUserTitlesRow, error) {
|
|
rows, err := q.db.Query(ctx, searchUserTitles,
|
|
arg.UserID,
|
|
arg.Forward,
|
|
arg.SortBy,
|
|
arg.CursorYear,
|
|
arg.CursorID,
|
|
arg.CursorRating,
|
|
arg.Word,
|
|
arg.TitleStatuses,
|
|
arg.UsertitleStatuses,
|
|
arg.Rate,
|
|
arg.Rating,
|
|
arg.ReleaseYear,
|
|
arg.ReleaseSeason,
|
|
arg.Limit,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []SearchUserTitlesRow{}
|
|
for rows.Next() {
|
|
var i SearchUserTitlesRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.TitleNames,
|
|
&i.PosterID,
|
|
&i.TitleStatus,
|
|
&i.Rating,
|
|
&i.RatingCount,
|
|
&i.ReleaseYear,
|
|
&i.ReleaseSeason,
|
|
&i.Season,
|
|
&i.EpisodesAired,
|
|
&i.EpisodesAll,
|
|
&i.UserID,
|
|
&i.UsertitleStatus,
|
|
&i.UserRate,
|
|
&i.ReviewID,
|
|
&i.UserCtime,
|
|
&i.TitleStorageType,
|
|
&i.TitleImagePath,
|
|
&i.TagNames,
|
|
&i.StudioName,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const updateUser = `-- name: UpdateUser :one
|
|
UPDATE users
|
|
SET
|
|
avatar_id = COALESCE($1, avatar_id),
|
|
disp_name = COALESCE($2, disp_name),
|
|
user_desc = COALESCE($3, user_desc),
|
|
mail = COALESCE($4, mail)
|
|
WHERE id = $5
|
|
RETURNING id, avatar_id, nickname, disp_name, user_desc, creation_date, mail
|
|
`
|
|
|
|
type UpdateUserParams struct {
|
|
AvatarID *int64 `json:"avatar_id"`
|
|
DispName *string `json:"disp_name"`
|
|
UserDesc *string `json:"user_desc"`
|
|
Mail *string `json:"mail"`
|
|
UserID int64 `json:"user_id"`
|
|
}
|
|
|
|
type UpdateUserRow struct {
|
|
ID int64 `json:"id"`
|
|
AvatarID *int64 `json:"avatar_id"`
|
|
Nickname string `json:"nickname"`
|
|
DispName *string `json:"disp_name"`
|
|
UserDesc *string `json:"user_desc"`
|
|
CreationDate time.Time `json:"creation_date"`
|
|
Mail *string `json:"mail"`
|
|
}
|
|
|
|
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (UpdateUserRow, error) {
|
|
row := q.db.QueryRow(ctx, updateUser,
|
|
arg.AvatarID,
|
|
arg.DispName,
|
|
arg.UserDesc,
|
|
arg.Mail,
|
|
arg.UserID,
|
|
)
|
|
var i UpdateUserRow
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.AvatarID,
|
|
&i.Nickname,
|
|
&i.DispName,
|
|
&i.UserDesc,
|
|
&i.CreationDate,
|
|
&i.Mail,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const updateUserTitle = `-- name: UpdateUserTitle :one
|
|
UPDATE usertitles
|
|
SET
|
|
status = COALESCE($1::usertitle_status_t, status),
|
|
rate = COALESCE($2::int, rate)
|
|
WHERE
|
|
user_id = $3
|
|
AND title_id = $4
|
|
RETURNING user_id, title_id, status, rate, review_id, ctime
|
|
`
|
|
|
|
type UpdateUserTitleParams struct {
|
|
Status *UsertitleStatusT `json:"status"`
|
|
Rate *int32 `json:"rate"`
|
|
UserID int64 `json:"user_id"`
|
|
TitleID int64 `json:"title_id"`
|
|
}
|
|
|
|
// Fails with sql.ErrNoRows if (user_id, title_id) not found
|
|
func (q *Queries) UpdateUserTitle(ctx context.Context, arg UpdateUserTitleParams) (Usertitle, error) {
|
|
row := q.db.QueryRow(ctx, updateUserTitle,
|
|
arg.Status,
|
|
arg.Rate,
|
|
arg.UserID,
|
|
arg.TitleID,
|
|
)
|
|
var i Usertitle
|
|
err := row.Scan(
|
|
&i.UserID,
|
|
&i.TitleID,
|
|
&i.Status,
|
|
&i.Rate,
|
|
&i.ReviewID,
|
|
&i.Ctime,
|
|
)
|
|
return i, err
|
|
}
|