From 604b54df1adc4e3eb038c10fc2b8ce962f910547 Mon Sep 17 00:00:00 2001 From: jasinco Date: Wed, 4 Jun 2025 18:51:28 +0800 Subject: [PATCH] combine two query of posts and images, remove comment and add emit_json tag to sqlc config --- internal/handlers/post.go | 59 +----------- nimdb/models.go | 50 +++++----- nimdb/query.sql.go | 191 +++++++++++++++----------------------- sql/query.sql | 19 ++-- sqlc.yml | 2 +- 5 files changed, 114 insertions(+), 207 deletions(-) diff --git a/internal/handlers/post.go b/internal/handlers/post.go index 5993abc..bfa8020 100644 --- a/internal/handlers/post.go +++ b/internal/handlers/post.go @@ -1,7 +1,6 @@ package handlers import ( - "context" "crypto/sha256" "encoding/base64" "log" @@ -18,16 +17,6 @@ import ( "nim.jasinco.work/app/nimdb" ) -type Post struct { - ID int32 `json:"id"` - Content string `json:"content"` - Heart int32 `json:"heart"` - Enclosure []string `json:"enclosure"` - Signing pgtype.Text `json:"signing"` - PostAt pgtype.Timestamptz `json:"post_at"` - IGid pgtype.Text `json:"igid"` -} - var supported_filetype = []string{"image/png", "image/jpeg", "image/webp", "image/gif", "image/heif", "video/H264", "video/H265", "video/mp4"} func find_supported(mimetype string) bool { @@ -63,27 +52,18 @@ func Fetch_post(c *fiber.Ctx) error { rec[id] = nimdb.GetPostRow(val) } } else { - return c.SendStatus(fiber.StatusBadRequest) + return c.Status(fiber.StatusBadRequest).SendString("Can't parse cursor") } if len(rec) == 0 { return c.SendStatus(fiber.StatusNoContent) } - var rec_with_media []Post = make([]Post, len(rec)) - for i, val := range rec { - rec_with_media[i] = Post{ID: val.ID, Content: val.Content, Signing: val.Signing, PostAt: val.PostAt, Heart: val.Heart, IGid: val.Igid} - media, err := internal.NIMDB.GetPostMedia(ctx, pgtype.Int4{Int32: val.ID, Valid: true}) - if err != nil { - log.Println(err) - return fiber.ErrInternalServerError - } - rec_with_media[i].Enclosure = media - } - return c.JSON(rec_with_media) + return c.JSON(rec) } func Delete_post(c *fiber.Ctx) error { post := c.Query("post") + hash := c.Query("hash") ctx := c.Context() post_id, err := strconv.Atoi(post) if err != nil { @@ -96,7 +76,7 @@ func Delete_post(c *fiber.Ctx) error { } defer tx.Rollback(ctx) qtx := internal.NIMDB.WithTx(tx) - if err = qtx.DeletePost(ctx, int32(post_id)); err != nil { + if err = qtx.DeletePost(ctx, nimdb.DeletePostParams{ID: int32(post_id), Hash: hash}); err != nil { return err } if err = qtx.InvalidateMedia(ctx, pgtype.Int4{Int32: int32(post_id)}); err != nil { @@ -110,36 +90,6 @@ func Delete_post(c *fiber.Ctx) error { return c.SendStatus(200) } -func Fetch_comment(c *fiber.Ctx) error { - cursor := c.Query("cursor") - post, err := strconv.Atoi(c.Query("post")) - if err != nil { - return c.Status(500).SendString("Failed to parse Int") - } - - ctx := context.Background() - conn, err := internal.POOL.Acquire(ctx) - if err != nil { - return c.Status(500).SendString("Failed to Acuire DB") - } - defer conn.Release() - db := nimdb.New(conn) - - var rec []nimdb.GetCommentRow - if len(cursor) == 0 { - rec, err = db.GetComment(ctx, nimdb.GetCommentParams{PostID: int32(post), Limit: 10}) - } else if cursor_num, err := strconv.Atoi(cursor); err == nil { - rec_cur, err := db.GetCommentWithCursor(ctx, nimdb.GetCommentWithCursorParams{ID: int32(cursor_num), PostID: int32(post), Limit: 10}) - if err != nil { - return c.Status(500).SendString("Failed to Parse Query DB") - } - rec = make([]nimdb.GetCommentRow, len(rec_cur)) - for id, val := range rec_cur { - rec[id] = nimdb.GetCommentRow(val) - } - } - return c.JSON(rec) -} func Insert_Post(c *fiber.Ctx) error { ctx := c.Context() @@ -203,6 +153,7 @@ func Insert_Post(c *fiber.Ctx) error { fxnamepath := filetype + "/" + mid.String() if err = c.SaveFile(file, path.Join("./static", fxnamepath)); err != nil { + log.Println("Can't save to ./static", err.Error()) return fiber.ErrInternalServerError } diff --git a/nimdb/models.go b/nimdb/models.go index 3693425..0131c80 100644 --- a/nimdb/models.go +++ b/nimdb/models.go @@ -34,8 +34,8 @@ func (e *PostPhase) Scan(src interface{}) error { } type NullPostPhase struct { - PostPhase PostPhase - Valid bool // Valid is true if PostPhase is not NULL + PostPhase PostPhase `json:"post_phase"` + Valid bool `json:"valid"` // Valid is true if PostPhase is not NULL } // Scan implements the Scanner interface. @@ -57,36 +57,36 @@ func (ns NullPostPhase) Value() (driver.Value, error) { } type Admin struct { - Username string - Password string - Totp string - Super bool + Username string `json:"username"` + Password string `json:"password"` + Totp string `json:"totp"` + Super bool `json:"super"` } type Comment struct { - ID int32 - PostID int32 - Content string - Signing pgtype.Text - Hash string - PostAt pgtype.Timestamptz - Heart int32 + ID int32 `json:"id"` + PostID int32 `json:"post_id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + Hash string `json:"hash"` + PostAt pgtype.Timestamptz `json:"post_at"` + Heart int32 `json:"heart"` } type Medium struct { - Url string - PostID pgtype.Int4 - CommentID pgtype.Int4 - Visible pgtype.Bool + Url string `json:"url"` + PostID pgtype.Int4 `json:"post_id"` + CommentID pgtype.Int4 `json:"comment_id"` + Visible pgtype.Bool `json:"visible"` } type Post struct { - ID int32 - Content string - Signing pgtype.Text - Hash string - PostAt pgtype.Timestamptz - Heart int32 - Phase PostPhase - Igid pgtype.Text + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + Hash string `json:"hash"` + PostAt pgtype.Timestamptz `json:"post_at"` + Heart int32 `json:"heart"` + Phase PostPhase `json:"phase"` + Igid pgtype.Text `json:"igid"` } diff --git a/nimdb/query.sql.go b/nimdb/query.sql.go index 89ff850..817591d 100644 --- a/nimdb/query.sql.go +++ b/nimdb/query.sql.go @@ -38,9 +38,9 @@ INSERT INTO admin (username, password, totp) VALUES ($1, $2,$3) ` type AdminCreateAccountParams struct { - Username string - Password string - Totp string + Username string `json:"username"` + Password string `json:"password"` + Totp string `json:"totp"` } func (q *Queries) AdminCreateAccount(ctx context.Context, arg AdminCreateAccountParams) error { @@ -77,10 +77,10 @@ SELECT id, content, signing, post_at FROM posts WHERE phase = 'pending' ORDER BY ` type AdminGetPostRow struct { - ID int32 - Content string - Signing pgtype.Text - PostAt pgtype.Timestamptz + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + PostAt pgtype.Timestamptz `json:"post_at"` } func (q *Queries) AdminGetPost(ctx context.Context) ([]AdminGetPostRow, error) { @@ -113,13 +113,13 @@ SELECT totp, super FROM admin WHERE username = $1 AND password = $2 ` type AdminLoginGetTOTPParams struct { - Username string - Password string + Username string `json:"username"` + Password string `json:"password"` } type AdminLoginGetTOTPRow struct { - Totp string - Super bool + Totp string `json:"totp"` + Super bool `json:"super"` } func (q *Queries) AdminLoginGetTOTP(ctx context.Context, arg AdminLoginGetTOTPParams) (AdminLoginGetTOTPRow, error) { @@ -143,8 +143,8 @@ UPDATE posts SET phase = $1 WHERE id=$2 AND phase = 'pending' RETURNING id ` type AdminVerifyParams struct { - Phase PostPhase - ID int32 + Phase PostPhase `json:"phase"` + ID int32 `json:"id"` } func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32, error) { @@ -155,11 +155,16 @@ func (q *Queries) AdminVerify(ctx context.Context, arg AdminVerifyParams) (int32 } const deletePost = `-- name: DeletePost :exec -UPDATE posts SET phase = 'deleted' WHERE id = $1 +UPDATE posts SET phase = 'deleted' WHERE id = $1 AND hash=$2 ` -func (q *Queries) DeletePost(ctx context.Context, id int32) error { - _, err := q.db.Exec(ctx, deletePost, id) +type DeletePostParams struct { + ID int32 `json:"id"` + Hash string `json:"hash"` +} + +func (q *Queries) DeletePost(ctx context.Context, arg DeletePostParams) error { + _, err := q.db.Exec(ctx, deletePost, arg.ID, arg.Hash) return err } @@ -172,15 +177,15 @@ LIMIT $2 ` type GetCommentParams struct { - PostID int32 - Limit int32 + PostID int32 `json:"post_id"` + Limit int32 `json:"limit"` } type GetCommentRow struct { - ID int32 - Content string - Signing pgtype.Text - PostAt pgtype.Timestamptz + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + PostAt pgtype.Timestamptz `json:"post_at"` } func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCommentRow, error) { @@ -208,32 +213,6 @@ func (q *Queries) GetComment(ctx context.Context, arg GetCommentParams) ([]GetCo return items, nil } -const getCommentMedia = `-- name: GetCommentMedia :many -SELECT url -FROM media -WHERE comment_id=$1 AND visible = true -` - -func (q *Queries) GetCommentMedia(ctx context.Context, commentID pgtype.Int4) ([]string, error) { - rows, err := q.db.Query(ctx, getCommentMedia, commentID) - if err != nil { - return nil, err - } - defer rows.Close() - var items []string - for rows.Next() { - var url string - if err := rows.Scan(&url); err != nil { - return nil, err - } - items = append(items, url) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - const getCommentWithCursor = `-- name: GetCommentWithCursor :many SELECT id, content, signing, post_at FROM comment @@ -243,16 +222,16 @@ LIMIT $3 ` type GetCommentWithCursorParams struct { - ID int32 - PostID int32 - Limit int32 + ID int32 `json:"id"` + PostID int32 `json:"post_id"` + Limit int32 `json:"limit"` } type GetCommentWithCursorRow struct { - ID int32 - Content string - Signing pgtype.Text - PostAt pgtype.Timestamptz + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + PostAt pgtype.Timestamptz `json:"post_at"` } func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCursorParams) ([]GetCommentWithCursorRow, error) { @@ -281,20 +260,23 @@ func (q *Queries) GetCommentWithCursor(ctx context.Context, arg GetCommentWithCu } const getPost = `-- name: GetPost :many -SELECT id, content, signing, post_at, heart, igid +SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure FROM posts +LEFT JOIN media ON post_id is not null AND post_id = id AND visible WHERE phase = 'ok' +GROUP BY id ORDER BY id DESC LIMIT $1 ` type GetPostRow struct { - ID int32 - Content string - Signing pgtype.Text - PostAt pgtype.Timestamptz - Heart int32 - Igid pgtype.Text + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + PostAt pgtype.Timestamptz `json:"post_at"` + Heart int32 `json:"heart"` + Igid pgtype.Text `json:"igid"` + Enclosure interface{} `json:"enclosure"` } func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error) { @@ -313,6 +295,7 @@ func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error &i.PostAt, &i.Heart, &i.Igid, + &i.Enclosure, ); err != nil { return nil, err } @@ -324,52 +307,29 @@ func (q *Queries) GetPost(ctx context.Context, limit int32) ([]GetPostRow, error return items, nil } -const getPostMedia = `-- name: GetPostMedia :many -SELECT url -FROM media -WHERE post_id=$1 AND visible = true -` - -func (q *Queries) GetPostMedia(ctx context.Context, postID pgtype.Int4) ([]string, error) { - rows, err := q.db.Query(ctx, getPostMedia, postID) - if err != nil { - return nil, err - } - defer rows.Close() - var items []string - for rows.Next() { - var url string - if err := rows.Scan(&url); err != nil { - return nil, err - } - items = append(items, url) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - const getPostWithCursor = `-- name: GetPostWithCursor :many -SELECT id, content, signing, post_at, heart, igid +SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure FROM posts +LEFT JOIN media ON post_id is not null AND post_id = id AND visible WHERE id <= $1 AND phase = 'ok' +GROUP BY id ORDER BY id DESC LIMIT $2 ` type GetPostWithCursorParams struct { - ID int32 - Limit int32 + ID int32 `json:"id"` + Limit int32 `json:"limit"` } type GetPostWithCursorRow struct { - ID int32 - Content string - Signing pgtype.Text - PostAt pgtype.Timestamptz - Heart int32 - Igid pgtype.Text + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + PostAt pgtype.Timestamptz `json:"post_at"` + Heart int32 `json:"heart"` + Igid pgtype.Text `json:"igid"` + Enclosure interface{} `json:"enclosure"` } func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorParams) ([]GetPostWithCursorRow, error) { @@ -388,6 +348,7 @@ func (q *Queries) GetPostWithCursor(ctx context.Context, arg GetPostWithCursorPa &i.PostAt, &i.Heart, &i.Igid, + &i.Enclosure, ); err != nil { return nil, err } @@ -404,8 +365,8 @@ INSERT INTO media (url, comment_id) VALUES ($1, $2) ` type InsertCommentImageParams struct { - Url string - CommentID pgtype.Int4 + Url string `json:"url"` + CommentID pgtype.Int4 `json:"comment_id"` } func (q *Queries) InsertCommentImage(ctx context.Context, arg InsertCommentImageParams) error { @@ -420,14 +381,14 @@ RETURNING id,hash ` type InsertPostParams struct { - Content string - Signing pgtype.Text - Hash string + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + Hash string `json:"hash"` } type InsertPostRow struct { - ID int32 - Hash string + ID int32 `json:"id"` + Hash string `json:"hash"` } func (q *Queries) InsertPost(ctx context.Context, arg InsertPostParams) (InsertPostRow, error) { @@ -442,8 +403,8 @@ INSERT INTO media (url, post_id) VALUES ($1, $2) ` type InsertPostImageParams struct { - Url string - PostID pgtype.Int4 + Url string `json:"url"` + PostID pgtype.Int4 `json:"post_id"` } func (q *Queries) InsertPostImage(ctx context.Context, arg InsertPostImageParams) error { @@ -465,11 +426,11 @@ SELECT id, content, signing, post_at, phase FROM posts WHERE phase = 'pending' O ` type SuperAdminGetPostRow struct { - ID int32 - Content string - Signing pgtype.Text - PostAt pgtype.Timestamptz - Phase PostPhase + ID int32 `json:"id"` + Content string `json:"content"` + Signing pgtype.Text `json:"signing"` + PostAt pgtype.Timestamptz `json:"post_at"` + Phase PostPhase `json:"phase"` } func (q *Queries) SuperAdminGetPost(ctx context.Context) ([]SuperAdminGetPostRow, error) { @@ -503,8 +464,8 @@ UPDATE posts SET phase = $1 WHERE id=$2 AND (phase = 'pending' OR phase = 'rejec ` type SuperAdminVerifyParams struct { - Phase PostPhase - ID int32 + Phase PostPhase `json:"phase"` + ID int32 `json:"id"` } func (q *Queries) SuperAdminVerify(ctx context.Context, arg SuperAdminVerifyParams) (int32, error) { @@ -519,8 +480,8 @@ UPDATE posts set igid = $1 WHERE id = $2 ` type UpdatePostIGIDParams struct { - Igid pgtype.Text - ID int32 + Igid pgtype.Text `json:"igid"` + ID int32 `json:"id"` } func (q *Queries) UpdatePostIGID(ctx context.Context, arg UpdatePostIGIDParams) error { diff --git a/sql/query.sql b/sql/query.sql index b376922..419c5b9 100644 --- a/sql/query.sql +++ b/sql/query.sql @@ -1,14 +1,18 @@ -- name: GetPost :many -SELECT id, content, signing, post_at, heart, igid +SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure FROM posts +LEFT JOIN media ON post_id is not null AND post_id = id AND visible WHERE phase = 'ok' +GROUP BY id ORDER BY id DESC LIMIT $1; -- name: GetPostWithCursor :many -SELECT id, content, signing, post_at, heart, igid +SELECT id, content, signing, post_at, heart, igid, array_agg(url) as enclosure FROM posts +LEFT JOIN media ON post_id is not null AND post_id = id AND visible WHERE id <= $1 AND phase = 'ok' +GROUP BY id ORDER BY id DESC LIMIT $2; @@ -21,7 +25,7 @@ RETURNING id,hash; UPDATE posts set igid = $1 WHERE id = $2; -- name: DeletePost :exec -UPDATE posts SET phase = 'deleted' WHERE id = $1; +UPDATE posts SET phase = 'deleted' WHERE id = $1 AND hash=$2; -- name: InvalidateMedia :exec UPDATE media SET visible = false WHERE post_id = $1; @@ -40,15 +44,6 @@ WHERE id <= $1 AND phase = 'ok' AND post_id = $2 ORDER BY id DESC LIMIT $3; --- name: GetPostMedia :many -SELECT url -FROM media -WHERE post_id=$1 AND visible = true; - --- name: GetCommentMedia :many -SELECT url -FROM media -WHERE comment_id=$1 AND visible = true; -- name: InsertPostImage :exec INSERT INTO media (url, post_id) VALUES ($1, $2); diff --git a/sqlc.yml b/sqlc.yml index 1f2ac13..e18e62e 100644 --- a/sqlc.yml +++ b/sqlc.yml @@ -8,4 +8,4 @@ sql: package: "nimdb" out: "nimdb" sql_package: "pgx/v5" - + emit_json_tags: true