s1llyw0rdz/storage/status.go

220 lines
5.3 KiB
Go
Raw Normal View History

2021-11-22 08:05:57 +00:00
package storage
import (
2021-11-22 17:12:07 +00:00
"context"
2021-11-22 08:05:57 +00:00
"database/sql"
"status/model"
"strconv"
"strings"
)
type statusQueryBuilder struct {
where string
limit string
offset string
}
func (p statusQueryBuilder) build() string {
2021-11-30 20:50:10 +00:00
query := []string{`SELECT id, author, content, created_at, face from statuses`}
2021-11-22 08:05:57 +00:00
if p.where != "" {
query = append(query, `WHERE`, p.where)
}
query = append(query, `ORDER BY created_at desc`)
if p.limit != "" {
query = append(query, `LIMIT`, p.limit)
}
if p.offset != "" {
query = append(query, `OFFSET`, p.offset)
}
return strings.Join(query, " ")
}
func (s *Storage) populateStatus(rows *sql.Rows) (model.Status, error) {
var status model.Status
2021-11-30 20:50:10 +00:00
err := rows.Scan(&status.Id, &status.User, &status.Content, &status.CreatedAt, &status.Face)
2021-11-22 08:05:57 +00:00
if err != nil {
return status, err
}
return status, nil
}
2021-11-22 17:12:07 +00:00
func (s *Storage) CreateStatus(status model.Status) error {
var statusId int64
ctx := context.Background()
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return err
}
2021-11-30 20:50:10 +00:00
if err := tx.QueryRowContext(ctx, `INSERT INTO statuses (author, content, face) VALUES ($1, $2, $3) RETURNING id`,
status.User, status.Content, status.Face).Scan(&statusId); err != nil {
2021-11-22 17:12:07 +00:00
tx.Rollback()
return err
}
if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, statusId, status.User); err != nil {
tx.Rollback()
return err
}
err = tx.Commit()
return err
2021-11-22 08:05:57 +00:00
}
func (s *Storage) StatusById(id int64) (model.Status, error) {
var status model.Status
err := s.db.QueryRow(
2022-02-20 07:03:39 +00:00
`SELECT id, author, content, face, created_at from statuses WHERE id=$1`, id).Scan(
2021-11-22 08:05:57 +00:00
&status.Id,
&status.User,
&status.Content,
2021-12-02 20:41:17 +00:00
&status.Face,
2022-02-20 07:03:39 +00:00
&status.CreatedAt,
2021-11-22 08:05:57 +00:00
)
return status, err
}
2021-11-26 22:36:48 +00:00
func (s *Storage) StatusByUsername(user string, perPage int, page int64) ([]model.Status, bool, error) {
2021-11-22 08:05:57 +00:00
rows, err := s.db.Query(statusQueryBuilder{
where: `author = $1`,
limit: strconv.Itoa(perPage + 1),
offset: `$2`,
}.build(), user, page*int64(perPage))
if err != nil {
2021-11-26 22:36:48 +00:00
return nil, false, err
2021-11-22 08:05:57 +00:00
}
var statuses []model.Status
for rows.Next() {
post, err := s.populateStatus(rows)
if err != nil {
2021-11-26 22:36:48 +00:00
return nil, false, err
2021-11-22 08:05:57 +00:00
}
statuses = append(statuses, post)
}
if len(statuses) > perPage {
2021-11-26 22:36:48 +00:00
return statuses[0:perPage], true, err
2021-11-22 08:05:57 +00:00
}
2021-11-26 22:36:48 +00:00
return statuses, false, err
2021-11-22 08:05:57 +00:00
}
2021-12-10 17:48:24 +00:00
func (s *Storage) StatusFeed() ([]model.Status, error) {
rows, err := s.db.Query(statusQueryBuilder{
limit: strconv.Itoa(20),
}.build())
if err != nil {
return nil, err
}
var statuses []model.Status
for rows.Next() {
post, err := s.populateStatus(rows)
if err != nil {
return nil, err
}
statuses = append(statuses, post)
}
return statuses, err
}
2021-11-22 08:05:57 +00:00
func (s *Storage) Statuses(page int64, perPage int) ([]model.Status, bool, error) {
rows, err := s.db.Query(statusQueryBuilder{
limit: strconv.Itoa(perPage + 1),
offset: `$1`,
}.build(), page*int64(perPage))
if err != nil {
return nil, false, err
}
var statuses []model.Status
for rows.Next() {
post, err := s.populateStatus(rows)
if err != nil {
return statuses, false, err
}
statuses = append(statuses, post)
}
if len(statuses) > perPage {
return statuses[0:perPage], true, err
}
return statuses, false, err
}
2021-11-22 17:12:07 +00:00
func (s *Storage) LatestStatuses() ([]model.Status, error) {
rows, err := s.db.Query(`
select
statuses.id,
users.name,
statuses.content,
2021-11-30 20:50:10 +00:00
statuses.created_at,
statuses.face
2021-11-22 17:12:07 +00:00
from
users
inner join statuses
on users.status_id = statuses.id
order by statuses.created_at desc;
`)
if err != nil {
return nil, err
}
var statuses []model.Status
for rows.Next() {
post, err := s.populateStatus(rows)
if err != nil {
return statuses, err
}
statuses = append(statuses, post)
}
return statuses, err
}
2021-11-22 08:05:57 +00:00
func (s *Storage) UpdateStatus(status model.Status) error {
2021-11-30 20:50:10 +00:00
stmt, err := s.db.Prepare(`UPDATE statuses SET content = $1, face = $2 WHERE id = $3 and author = $4;`)
2021-11-22 08:05:57 +00:00
if err != nil {
return err
}
2021-11-30 20:50:10 +00:00
_, err = stmt.Exec(status.Content, status.Face, status.Id, status.User)
2021-11-22 08:05:57 +00:00
return err
}
func (s *Storage) DeleteStatus(id int64, author string) error {
2021-11-27 09:39:34 +00:00
ctx := context.Background()
tx, err := s.db.BeginTx(ctx, nil)
2021-11-22 08:05:57 +00:00
if err != nil {
return err
}
2021-11-27 09:39:34 +00:00
var latestId int64
if err := tx.QueryRowContext(ctx, `select status_id from users where name = $1`,
author).Scan(&latestId); err != nil {
tx.Rollback()
return err
}
if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, nil, author); err != nil {
tx.Rollback()
return err
}
if _, err := tx.ExecContext(ctx, `DELETE from statuses WHERE id = $1 and author = $2;`, id, author); err != nil {
tx.Rollback()
return err
}
if latestId == id {
var newId int64
if err := tx.QueryRowContext(ctx, `select id from statuses where author = $1 order by created_at desc limit 1;`,
author).Scan(&newId); err != nil {
2021-11-27 09:56:12 +00:00
if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, nil, author); err != nil {
tx.Rollback()
return err
}
err = tx.Commit()
2021-11-27 09:39:34 +00:00
return err
}
if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, newId, author); err != nil {
tx.Rollback()
return err
}
2021-11-30 20:50:10 +00:00
} else {
if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, latestId, author); err != nil {
tx.Rollback()
return err
}
2021-11-27 09:39:34 +00:00
}
2021-11-30 20:50:10 +00:00
2021-11-27 09:39:34 +00:00
err = tx.Commit()
2021-11-22 08:05:57 +00:00
return err
}