init(db): add credits get functions

This commit is contained in:
Masahiko AMANO 2025-01-18 20:29:09 +03:00
parent 8852317d71
commit db213bd559

202
internal/db/credits.go Normal file
View File

@ -0,0 +1,202 @@
package db
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/H1K0/Kiraku/internal/models"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
func CreditsGetByPerson(ctx context.Context, user_id, person_id, sort string) (credits []models.PersonCredit, statusCode int, err error) {
ok, _ := UserAuth(ctx, user_id)
if !ok {
err = fmt.Errorf("unauthorized")
statusCode = http.StatusUnauthorized
return
}
query := "SELECT t.id AS track_id, t.name AS track_name, t.duration AS track_duration, COALESCE(t.release_date::text, '') AS track_releaseDate, t.acquire_datetime AS track_acquireDatetime, r.id AS role_id, r.name AS role_name, COALESCE(c.alias, '') AS alias " +
"FROM credits c " +
"JOIN tracks t ON t.id=c.track_id " +
"JOIN roles r ON r.id=c.role_id " +
"WHERE c.person_id=$1"
if sort != "" {
sort_options := strings.Split(sort, ",")
query += " ORDER BY "
for i, sort_option := range sort_options {
sort_order := sort_option[:1]
sort_field := sort_option[1:]
switch sort_order {
case "+":
sort_order = "ASC"
case "-":
sort_order = "DESC"
default:
err = fmt.Errorf("invalid sorting order mark: %q", sort)
statusCode = http.StatusBadRequest
return
}
switch sort_field {
case "track.name":
fallthrough
case "track.releaseDate":
fallthrough
case "track.acquireDatetime":
fallthrough
case "track.duration":
fallthrough
case "role.name":
sort_field = strings.ReplaceAll(sort_field, ".", "_")
case "track.sortName":
sort_field = "COALESCE(t.sort_name, t.name)"
case "alias":
default:
err = fmt.Errorf("invalid sorting field: %q", sort_field)
statusCode = http.StatusBadRequest
return
}
if i > 0 {
query += ", "
}
query += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
}
}
row := connPool.QueryRow(ctx, "SELECT 1 FROM persons WHERE id=$1", person_id)
err = row.Scan(nil)
if err != nil {
if err == pgx.ErrNoRows {
err = fmt.Errorf("not found")
statusCode = http.StatusNotFound
return
}
pgErr := err.(*pgconn.PgError)
if pgErr.Code == "22P02" {
err = fmt.Errorf("%s", pgErr.Message)
statusCode = http.StatusBadRequest
} else {
statusCode = http.StatusInternalServerError
}
return
}
rows, err := connPool.Query(ctx, query, person_id)
if err != nil {
statusCode = http.StatusInternalServerError
return
}
count := 0
for rows.Next() {
var credit models.PersonCredit
err = rows.Scan(
&credit.Track.ID, &credit.Track.Name, &credit.Track.Duration, &credit.Track.ReleaseDate, &credit.Track.AcquireDatetime,
&credit.Role.ID, &credit.Role.Name, &credit.Alias,
)
if err != nil {
statusCode = http.StatusInternalServerError
return
}
credits = append(credits, credit)
count++
}
err = rows.Err()
if err != nil {
statusCode = http.StatusInternalServerError
return
}
statusCode = http.StatusOK
return
}
func CreditsGetByTrack(ctx context.Context, user_id, track_id, sort string) (credits []models.TrackCredit, statusCode int, err error) {
ok, _ := UserAuth(ctx, user_id)
if !ok {
err = fmt.Errorf("unauthorized")
statusCode = http.StatusUnauthorized
return
}
query := "SELECT p.id AS person_id, p.name AS person_name, COALESCE(p.sort_name, '') AS person_sortName, r.id AS role_id, r.name AS role_name, COALESCE(c.alias, '') AS alias " +
"FROM credits c " +
"JOIN persons p ON p.id=c.person_id " +
"JOIN roles r ON r.id=c.role_id " +
"WHERE c.track_id=$1"
if sort != "" {
sort_options := strings.Split(sort, ",")
query += " ORDER BY "
for i, sort_option := range sort_options {
sort_order := sort_option[:1]
sort_field := sort_option[1:]
switch sort_order {
case "+":
sort_order = "ASC"
case "-":
sort_order = "DESC"
default:
err = fmt.Errorf("invalid sorting order mark: %q", sort)
statusCode = http.StatusBadRequest
return
}
switch sort_field {
case "person.name":
fallthrough
case "role.name":
sort_field = strings.ReplaceAll(sort_field, ".", "_")
case "person.sortName":
sort_field = "COALESCE(p.sort_name, p.name)"
case "alias":
default:
err = fmt.Errorf("invalid sorting field: %q", sort_field)
statusCode = http.StatusBadRequest
return
}
if i > 0 {
query += ", "
}
query += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
}
}
row := connPool.QueryRow(ctx, "SELECT 1 FROM tracks WHERE id=$1", track_id)
err = row.Scan(nil)
if err != nil {
if err == pgx.ErrNoRows {
err = fmt.Errorf("not found")
statusCode = http.StatusNotFound
return
}
pgErr := err.(*pgconn.PgError)
if pgErr.Code == "22P02" {
err = fmt.Errorf("%s", pgErr.Message)
statusCode = http.StatusBadRequest
} else {
statusCode = http.StatusInternalServerError
}
return
}
rows, err := connPool.Query(ctx, query, track_id)
if err != nil {
statusCode = http.StatusInternalServerError
return
}
count := 0
for rows.Next() {
var credit models.TrackCredit
err = rows.Scan(
&credit.Person.ID, &credit.Person.Name, &credit.Person.SortName,
&credit.Role.ID, &credit.Role.Name, &credit.Alias,
)
if err != nil {
statusCode = http.StatusInternalServerError
return
}
credits = append(credits, credit)
count++
}
err = rows.Err()
if err != nil {
statusCode = http.StatusInternalServerError
return
}
statusCode = http.StatusOK
return
}