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:
parent
e7e9a360f9
commit
b966604d1d
8 changed files with 97 additions and 14 deletions
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue