From 291787a5efaa2352241a25bcd75ff69eac23c4f0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 26 Oct 2022 20:42:45 +0800 Subject: [PATCH] Fix issues count bug (#21600) backport #21557 --- models/issues/comment.go | 2 +- models/issues/issue.go | 12 ++------ models/repo.go | 13 +++------ models/repo/repo.go | 61 +++++++++++++++++----------------------- 4 files changed, 33 insertions(+), 55 deletions(-) diff --git a/models/issues/comment.go b/models/issues/comment.go index a4e69e711..258ef0cb5 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -881,7 +881,7 @@ func updateCommentInfos(ctx context.Context, opts *CreateCommentOptions, comment } } case CommentTypeReopen, CommentTypeClose: - if err = updateIssueClosedNum(ctx, opts.Issue); err != nil { + if err = repo_model.UpdateRepoIssueNumbers(ctx, opts.Issue.RepoID, opts.Issue.IsPull, true); err != nil { return err } } diff --git a/models/issues/issue.go b/models/issues/issue.go index 76a0ea7d0..814f3d934 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -722,7 +722,8 @@ func doChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.Use } } - if err := updateIssueClosedNum(ctx, issue); err != nil { + // update repository's issue closed number + if err := repo_model.UpdateRepoIssueNumbers(ctx, issue.RepoID, issue.IsPull, true); err != nil { return nil, err } @@ -2104,15 +2105,6 @@ func (issue *Issue) BlockingDependencies(ctx context.Context) (issueDeps []*Depe return issueDeps, err } -func updateIssueClosedNum(ctx context.Context, issue *Issue) (err error) { - if issue.IsPull { - err = repo_model.StatsCorrectNumClosed(ctx, issue.RepoID, true, "num_closed_pulls") - } else { - err = repo_model.StatsCorrectNumClosed(ctx, issue.RepoID, false, "num_closed_issues") - } - return -} - // FindAndUpdateIssueMentions finds users mentioned in the given content string, and saves them in the database. func FindAndUpdateIssueMentions(ctx context.Context, issue *Issue, doer *user_model.User, content string) (mentions []*user_model.User, err error) { rawMentions := references.FindAllMentionsMarkdown(content) diff --git a/models/repo.go b/models/repo.go index e304abf96..bc2601c9a 100644 --- a/models/repo.go +++ b/models/repo.go @@ -562,24 +562,19 @@ func repoStatsCorrectIssueNumComments(ctx context.Context, id int64) error { } func repoStatsCorrectNumIssues(ctx context.Context, id int64) error { - return repoStatsCorrectNum(ctx, id, false, "num_issues") + return repo_model.UpdateRepoIssueNumbers(ctx, id, false, false) } func repoStatsCorrectNumPulls(ctx context.Context, id int64) error { - return repoStatsCorrectNum(ctx, id, true, "num_pulls") -} - -func repoStatsCorrectNum(ctx context.Context, id int64, isPull bool, field string) error { - _, err := db.GetEngine(ctx).Exec("UPDATE `repository` SET "+field+"=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_pull=?) WHERE id=?", id, isPull, id) - return err + return repo_model.UpdateRepoIssueNumbers(ctx, id, true, false) } func repoStatsCorrectNumClosedIssues(ctx context.Context, id int64) error { - return repo_model.StatsCorrectNumClosed(ctx, id, false, "num_closed_issues") + return repo_model.UpdateRepoIssueNumbers(ctx, id, false, true) } func repoStatsCorrectNumClosedPulls(ctx context.Context, id int64) error { - return repo_model.StatsCorrectNumClosed(ctx, id, true, "num_closed_pulls") + return repo_model.UpdateRepoIssueNumbers(ctx, id, true, true) } func statsQuery(args ...interface{}) func(context.Context) ([]map[string][]byte, error) { diff --git a/models/repo/repo.go b/models/repo/repo.go index f6097d2d6..e22e146b5 100644 --- a/models/repo/repo.go +++ b/models/repo/repo.go @@ -23,6 +23,8 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + + "xorm.io/builder" ) // ErrUserDoesNotHaveAccessToRepo represets an error where the user doesn't has access to a given repo. @@ -319,13 +321,7 @@ func (repo *Repository) LoadUnits(ctx context.Context) (err error) { // UnitEnabled if this repository has the given unit enabled func (repo *Repository) UnitEnabled(tp unit.Type) (result bool) { - if err := db.WithContext(func(ctx *db.Context) error { - result = repo.UnitEnabledCtx(ctx, tp) - return nil - }); err != nil { - log.Error("repo.UnitEnabled: %v", err) - } - return + return repo.UnitEnabledCtx(db.DefaultContext, tp) } // UnitEnabled if this repository has the given unit enabled @@ -760,33 +756,28 @@ func CountRepositories(ctx context.Context, opts CountRepositoryOptions) (int64, return count, nil } -// StatsCorrectNumClosed update repository's issue related numbers -func StatsCorrectNumClosed(ctx context.Context, id int64, isPull bool, field string) error { - _, err := db.Exec(ctx, "UPDATE `repository` SET "+field+"=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=? AND is_pull=?) WHERE id=?", id, true, isPull, id) +// UpdateRepoIssueNumbers updates one of a repositories amount of (open|closed) (issues|PRs) with the current count +func UpdateRepoIssueNumbers(ctx context.Context, repoID int64, isPull, isClosed bool) error { + field := "num_" + if isClosed { + field += "closed_" + } + if isPull { + field += "pulls" + } else { + field += "issues" + } + + subQuery := builder.Select("count(*)"). + From("issue").Where(builder.Eq{ + "repo_id": repoID, + "is_pull": isPull, + }.And(builder.If(isClosed, builder.Eq{"is_closed": isClosed}))) + + // builder.Update(cond) will generate SQL like UPDATE ... SET cond + query := builder.Update(builder.Eq{field: subQuery}). + From("repository"). + Where(builder.Eq{"id": repoID}) + _, err := db.Exec(ctx, query) return err } - -// UpdateRepoIssueNumbers update repository issue numbers -func UpdateRepoIssueNumbers(ctx context.Context, repoID int64, isPull, isClosed bool) error { - e := db.GetEngine(ctx) - if isPull { - if _, err := e.ID(repoID).Decr("num_pulls").Update(new(Repository)); err != nil { - return err - } - if isClosed { - if _, err := e.ID(repoID).Decr("num_closed_pulls").Update(new(Repository)); err != nil { - return err - } - } - } else { - if _, err := e.ID(repoID).Decr("num_issues").Update(new(Repository)); err != nil { - return err - } - if isClosed { - if _, err := e.ID(repoID).Decr("num_closed_issues").Update(new(Repository)); err != nil { - return err - } - } - } - return nil -}