init(db): add persons get func

This commit is contained in:
Masahiko AMANO 2025-01-17 19:01:48 +03:00
parent 6f675b843c
commit cf444831f3

View File

@ -3,8 +3,11 @@ package db
import (
"context"
"fmt"
"net/http"
"strings"
"time"
"github.com/H1K0/Kiraku/internal/models"
"github.com/jackc/pgx/v5/pgxpool"
)
@ -44,3 +47,91 @@ func UserAuth(ctx context.Context, user_id string) (ok, editor bool) {
}
//#endregion Users
//#region Persons
func PersonsGet(ctx context.Context, user_id, filter, sort string, limit, offset int) (persons models.Persons, statusCode int, err error) {
if ok, _ := UserAuth(ctx, user_id); !ok {
err = fmt.Errorf("Unauthorized")
statusCode = http.StatusUnauthorized
return
}
queryGet := "SELECT id, name, coalesce(sort_name, '') FROM persons WHERE position($1 in lower(name))>0 OR position($1 in lower(sort_name))>0"
if sort != "" {
sort_options := strings.Split(sort, ",")
queryGet += " 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 "name":
case "sortName":
sort_field = "coalesce(sort_name, name)"
case "birthdate":
case "deathdate":
default:
err = fmt.Errorf("invalid sorting field: %q", sort_field)
statusCode = http.StatusBadRequest
return
}
if i > 0 {
queryGet += ", "
}
queryGet += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
}
}
queryCount := queryGet
if limit >= 0 {
queryGet += fmt.Sprintf(" LIMIT %d", limit)
}
if offset > 0 {
queryGet += fmt.Sprintf(" OFFSET %d", offset)
}
filter = strings.ToLower(filter)
rows, err := connPool.Query(ctx, queryGet, filter)
if err != nil {
statusCode = http.StatusInternalServerError
return
}
count := 0
for rows.Next() {
var person models.PersonBrief
err = rows.Scan(&person.ID, &person.Name, &person.SortName)
if err != nil {
err = fmt.Errorf("error while fetching persons: %w", err)
statusCode = http.StatusInternalServerError
return
}
persons.Persons = append(persons.Persons, person)
count++
}
err = rows.Err()
if err != nil {
statusCode = http.StatusInternalServerError
return
}
persons.Pagination.Limit = limit
persons.Pagination.Offset = offset
persons.Pagination.Count = count
queryCount = fmt.Sprintf("SELECT count(*) FROM (%s) tmp", queryCount)
row := connPool.QueryRow(ctx, queryCount, filter)
err = row.Scan(&persons.Pagination.Total)
if err != nil {
statusCode = http.StatusInternalServerError
} else {
statusCode = http.StatusOK
}
return
}
//#endregion Persons