1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-18 11:46:23 -07:00

Avoid using Select * in SQL queries, normalize some view columns

This commit is contained in:
Eggbertx 2025-01-12 14:01:36 -08:00
parent e7e9a360f9
commit b966604d1d
8 changed files with 97 additions and 14 deletions

View file

@ -118,12 +118,12 @@ func getAllPostsToDelete(postIDs []any, fileOnly bool) ([]delPost, []any, error)
params := postIDs
if fileOnly {
// only deleting this post's file, not subfiles if it's an OP
query = "SELECT * FROM DBPREFIXv_posts_to_delete_file_only WHERE postid IN " + setPart
query = "SELECT post_id, thread_id, op_id, is_top_post, filename, dir FROM DBPREFIXv_posts_to_delete_file_only WHERE post_id IN " + setPart
} else {
// deleting everything, including subfiles
params = append(params, postIDs...)
query = "SELECT * FROM DBPREFIXv_posts_to_delete WHERE postid IN " + setPart +
` OR thread_id IN (SELECT thread_id from DBPREFIXposts op WHERE opid IN ` + setPart + ` AND is_top_post)`
query = "SELECT post_id, thread_id, op_id, is_top_post, filename, dir FROM DBPREFIXv_posts_to_delete WHERE post_id IN " +
setPart + " OR thread_id IN (SELECT thread_id from DBPREFIXposts op WHERE op_id IN " + setPart + " AND is_top_post)"
}
rows, err := gcsql.QuerySQL(query, params...)
if err != nil {

View file

@ -35,9 +35,9 @@ func getFrontPagePosts() ([]frontPagePost, error) {
if siteCfg.RecentPostsWithNoFile {
// get recent posts, including those with no file
query = "SELECT * FROM DBPREFIXv_front_page_posts"
query = "SELECT id, message_raw, dir, filename, op_id FROM DBPREFIXv_front_page_posts"
} else {
query = "SELECT * FROM DBPREFIXv_front_page_posts_with_file"
query = "SELECT id, message_raw, dir, filename, op_id FROM DBPREFIXv_front_page_posts_with_file"
}
query += " ORDER BY id DESC LIMIT " + strconv.Itoa(siteCfg.MaxRecentPosts)

View file

@ -63,7 +63,10 @@ func (catalog *boardCatalog) fillPages(threadsPerPage int, threads []catalogThre
}
func getBoardTopPosts(board string) ([]*Post, error) {
const query = "SELECT * FROM DBPREFIXv_building_posts WHERE id = parent_id AND dir = ?"
const query = `SELECT id, thread_id, ip, name, tripcode, email, subject, created_on, last_modified, parent_id,
last_bump, message, message_raw, board_id, dir, original_filename, filename, checksum, filesize, tw, th,
width, height, locked, stickied, cyclical, flag, country, is_deleted
FROM DBPREFIXv_building_posts WHERE id = parent_id AND dir = ?`
var posts []*Post
err := QueryPosts(query, []any{board}, func(p *Post) error {

View file

@ -155,7 +155,10 @@ func QueryPosts(query string, params []any, cb func(*Post) error) error {
}
func GetBuildablePostsByIP(ip string, limit int) ([]*Post, error) {
query := "SELECT * FROM DBPREFIXv_building_posts WHERE ip = PARAM_ATON ORDER BY id DESC"
query := `SELECT id, thread_id, ip, name, tripcode, email, subject, created_on, last_modified, parent_id,
last_bump, message, message_raw, board_id, dir, original_filename, filename, checksum, filesize, tw, th,
width, height, locked, stickied, cyclical, flag, country, is_deleted
FROM DBPREFIXv_building_posts WHERE ip = PARAM_ATON ORDER BY id DESC`
if limit > 0 {
query += " LIMIT " + strconv.Itoa(limit)
}
@ -169,7 +172,10 @@ func GetBuildablePostsByIP(ip string, limit int) ([]*Post, error) {
}
func getThreadPosts(thread *gcsql.Thread) ([]*Post, error) {
const query = "SELECT * FROM DBPREFIXv_building_posts WHERE thread_id = ? ORDER BY id ASC"
const query = `SELECT id, thread_id, ip, name, tripcode, email, subject, created_on, last_modified, parent_id,
last_bump, message, message_raw, board_id, dir, original_filename, filename, checksum, filesize, tw, th,
width, height, locked, stickied, cyclical, flag, country, is_deleted
FROM DBPREFIXv_building_posts WHERE thread_id = ? ORDER BY id ASC`
var posts []*Post
err := QueryPosts(query, []any{thread.ID}, func(p *Post) error {
posts = append(posts, p)
@ -179,7 +185,10 @@ func getThreadPosts(thread *gcsql.Thread) ([]*Post, error) {
}
func GetRecentPosts(boardid int, limit int) ([]*Post, error) {
query := `SELECT * FROM DBPREFIXv_building_posts`
query := `SELECT id, thread_id, ip, name, tripcode, email, subject, created_on, last_modified, parent_id,
last_bump, message, message_raw, board_id, dir, original_filename, filename, checksum, filesize, tw, th,
width, height, locked, stickied, cyclical, flag, country, is_deleted
FROM DBPREFIXv_building_posts`
var args []any
if boardid > 0 {

View file

@ -337,6 +337,16 @@ func (p *Post) UnlinkUploads(leaveDeletedBox bool) error {
return err
}
// InCyclicalThread returns true if the post is in a cyclical thread
func (p *Post) InCyclicalThread() (bool, error) {
var cyclical bool
err := QueryRowTimeoutSQL(nil, "SELECT cyclical FROM DBPREFIXthreads WHERE id = ?", []any{p.ThreadID}, []any{&cyclical})
if errors.Is(err, sql.ErrNoRows) {
return false, ErrThreadDoesNotExist
}
return cyclical, err
}
// Delete sets the post as deleted and sets the deleted_at timestamp to the current time
func (p *Post) Delete() error {
if p.IsTopPost {
@ -413,6 +423,31 @@ func (p *Post) Insert(bumpThread bool, boardID int, locked bool, stickied bool,
return tx.Commit()
}
type cyclicalThreadPost struct {
PostID int // sql: post_id
}
// returns post IDs that should be deleted in a cyclical thread
// func (p *Post) postsToBeBumpedOff() ([]int, error) {
// ctx, cancel := context.WithTimeout(context.Background(), gcdb.defaultTimeout)
// defer cancel()
// tx, err := BeginContextTx(ctx)
// if err != nil {
// return nil, err
// }
// var cyclical bool
// if err = QueryRowContextSQL(ctx, tx, "SELECT cyclical FROM DBPREFIXthreads WHERE id = ?", []any{p.ThreadID}, []any{&cyclical}); err != nil {
// return nil, err
// }
// if !cyclical {
// return nil, nil
// }
// QueryContextSQL(ctx, tx, "SELECT post_id, thread_id, op_id, is_top_post, filename, dir FROM DBPREFIXv_posts_to_delete WHERE thread_id = ?")
// }
func (p *Post) WebPath() string {
if p.opID > 0 && p.boardDir != "" {
return config.WebPath(p.boardDir, "res/", strconv.Itoa(p.opID)+".html#"+strconv.Itoa(p.ID))

View file

@ -356,7 +356,8 @@ func fixThumbnailsCallback(_ http.ResponseWriter, request *http.Request, _ *gcsq
board := request.FormValue("board")
var uploads []uploadInfo
if board != "" {
const query = "SELECT * FROM DBPREFIXv_upload_info WHERE dir = ? ORDER BY created_on DESC"
const query = `SELECT id, op, filename, is_spoilered, width, height, thumbnail_width, thumbnail_height
FROM DBPREFIXv_upload_info WHERE dir = ? ORDER BY created_on DESC`
rows, err := gcsql.QuerySQL(query, board)
if err != nil {
return "", err

View file

@ -335,6 +335,7 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
isCyclical := request.PostFormValue("cyclical") == "on"
if isCyclical && boardConfig.CyclicalThreadNumPosts == 0 {
writer.WriteHeader(http.StatusBadRequest)
server.ServeError(writer, "Board does not support cyclical threads", wantsJSON, nil)
return
}
@ -460,17 +461,43 @@ func MakePost(writer http.ResponseWriter, request *http.Request) {
if err = config.TakeOwnership(filePath); err != nil {
errEv.Err(err).Caller().
Str("file", filePath).Send()
os.Remove(filePath)
os.Remove(thumbPath)
os.Remove(catalogThumbPath)
post.Delete()
server.ServeError(writer, err.Error(), wantsJSON, nil)
}
if err = config.TakeOwnership(thumbPath); err != nil {
errEv.Err(err).Caller().
Str("thumbnail", thumbPath).Send()
os.Remove(filePath)
os.Remove(thumbPath)
os.Remove(catalogThumbPath)
post.Delete()
server.ServeError(writer, err.Error(), wantsJSON, nil)
}
if err = config.TakeOwnership(catalogThumbPath); err != nil && !os.IsNotExist(err) {
errEv.Err(err).Caller().
Str("catalogThumbnail", catalogThumbPath).Send()
os.Remove(filePath)
os.Remove(thumbPath)
os.Remove(catalogThumbPath)
post.Delete()
server.ServeError(writer, err.Error(), wantsJSON, nil)
}
}
inCyclicalThread, err := post.InCyclicalThread()
if err != nil {
errEv.Err(err).Caller().Send()
server.ServeError(writer, "Unable to get thread info", wantsJSON, nil)
return
}
if inCyclicalThread {
// post is a cyclical thread
errEv.Bool("cyclical", inCyclicalThread)
}
// rebuild the board page
if err = building.BuildBoards(false, board.ID); err != nil {
server.ServeError(writer, "Unable to build boards", wantsJSON, nil)

View file

@ -8,6 +8,7 @@ DROP VIEW IF EXISTS DBPREFIXv_front_page_posts_with_file;
DROP VIEW IF EXISTS DBPREFIXv_front_page_posts;
DROP VIEW IF EXISTS DBPREFIXv_posts_to_delete_file_only;
DROP VIEW IF EXISTS DBPREFIXv_posts_to_delete;
DROP VIEW IF EXISTS DBPREFIXv_posts_cyclical_check;
DROP VIEW IF EXISTS DBPREFIXv_recent_posts;
DROP VIEW IF EXISTS DBPREFIXv_building_posts;
DROP VIEW IF EXISTS DBPREFIXv_top_post_thread_ids;
@ -42,10 +43,10 @@ INNER JOIN DBPREFIXv_top_post_thread_ids op ON op.thread_id = p.thread_id
WHERE p.is_deleted = FALSE;
CREATE VIEW DBPREFIXv_posts_to_delete AS
SELECT p.id AS postid, thread_id, (
SELECT op.id AS opid FROM DBPREFIXposts op
SELECT p.id AS post_id, thread_id, (
SELECT op.id AS op_id FROM DBPREFIXposts op
WHERE op.thread_id = p.thread_id AND is_top_post LIMIT 1
) as opid, is_top_post, COALESCE(filename, '') AS filename, dir
) as op_id, is_top_post, COALESCE(filename, '') AS filename, dir
FROM DBPREFIXboards b
LEFT JOIN DBPREFIXthreads t ON t.board_id = b.id
LEFT JOIN DBPREFIXposts p ON p.thread_id = t.id
@ -55,10 +56,17 @@ CREATE VIEW DBPREFIXv_posts_to_delete_file_only AS
SELECT * FROM DBPREFIXv_posts_to_delete
WHERE filename IS NOT NULL;
CREATE VIEW DBPREFIXv_posts_cyclical_check AS
SELECT post_id, d.thread_id, op_id, d.is_top_post, filename, dir
FROM DBPREFIXv_posts_to_delete d
INNER JOIN DBPREFIXposts p ON p.id = post_id
INNER JOIN DBPREFIXthreads t ON d.thread_id = t.id
WHERE p.is_deleted = 0 AND d.is_top_post = 0 and t.cyclical = 1;
CREATE VIEW DBPREFIXv_front_page_posts AS
SELECT DBPREFIXposts.id, DBPREFIXposts.message_raw,
(SELECT dir FROM DBPREFIXboards WHERE id = t.board_id) as dir,
COALESCE(f.filename, '') as filename, op.id as opid
COALESCE(f.filename, '') as filename, op.id as op_id
FROM DBPREFIXposts
LEFT JOIN DBPREFIXv_thread_board_ids t ON t.id = DBPREFIXposts.thread_id
LEFT JOIN (SELECT post_id, filename FROM DBPREFIXfiles) f on f.post_id = DBPREFIXposts.id