1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

Use conditions but not repo ids as query condition (#16839)

* Use conditions but not repo ids as query condition

* Improve the performance of pulls/issue

* Remove duplicated code

* fix lint

* Fix bug

* Fix stats

* More fixes

* Fix build

* Fix lint

* Fix test

* Fix build

* Adjust the logic

* Merge

* Fix conflicts

* improve the performance

* Add comments for the query conditions functions

* Some improvements
This commit is contained in:
Lunny Xiao
2021-12-29 21:02:12 +08:00
committed by GitHub
parent 8fa97a25f0
commit 8ce1b539b1
11 changed files with 401 additions and 427 deletions

View File

@@ -1186,6 +1186,9 @@ type IssuesOptions struct {
// prioritize issues from this repo
PriorityRepoID int64
IsArchived util.OptionalBool
Org *Organization // issues permission scope
Team *Team // issues permission scope
User *user_model.User // issues permission scope
}
// sortIssuesSession sort an issues-related session based on the provided
@@ -1337,6 +1340,44 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
From("milestone").
Where(builder.In("name", opts.IncludeMilestones)))
}
if opts.User != nil {
sess.And(
issuePullAccessibleRepoCond("issue.repo_id", opts.User.ID, opts.Org, opts.Team, opts.IsPull.IsTrue()),
)
}
}
// issuePullAccessibleRepoCond userID must not be zero, this condition require join repository table
func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *Organization, team *Team, isPull bool) builder.Cond {
var cond = builder.NewCond()
var unitType = unit.TypeIssues
if isPull {
unitType = unit.TypePullRequests
}
if org != nil {
if team != nil {
cond = cond.And(teamUnitsRepoCond(repoIDstr, userID, org.ID, team.ID, unitType)) // special team member repos
} else {
cond = cond.And(
builder.Or(
userOrgUnitRepoCond(repoIDstr, userID, org.ID, unitType), // team member repos
userOrgPublicUnitRepoCond(userID, org.ID), // user org public non-member repos, TODO: check repo has issues
),
)
}
} else {
cond = cond.And(
builder.Or(
userOwnedRepoCond(userID), // owned repos
userCollaborationRepoCond(repoIDstr, userID), // collaboration repos
userAssignedRepoCond(repoIDstr, userID), // user has been assigned accessible public repos
userMentionedRepoCond(repoIDstr, userID), // user has been mentioned accessible public repos
userCreateIssueRepoCond(repoIDstr, userID, isPull), // user has created issue/pr accessible public repos
),
)
}
return cond
}
func applyReposCondition(sess *xorm.Session, repoIDs []int64) *xorm.Session {
@@ -1646,15 +1687,16 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats,
// UserIssueStatsOptions contains parameters accepted by GetUserIssueStats.
type UserIssueStatsOptions struct {
UserID int64
RepoIDs []int64
UserRepoIDs []int64
FilterMode int
IsPull bool
IsClosed bool
IssueIDs []int64
IsArchived util.OptionalBool
LabelIDs []int64
UserID int64
RepoIDs []int64
FilterMode int
IsPull bool
IsClosed bool
IssueIDs []int64
IsArchived util.OptionalBool
LabelIDs []int64
Org *Organization
Team *Team
}
// GetUserIssueStats returns issue statistic information for dashboard by given conditions.
@@ -1671,28 +1713,34 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
cond = cond.And(builder.In("issue.id", opts.IssueIDs))
}
if opts.UserID > 0 {
cond = cond.And(issuePullAccessibleRepoCond("issue.repo_id", opts.UserID, opts.Org, opts.Team, opts.IsPull))
}
sess := func(cond builder.Cond) *xorm.Session {
s := db.GetEngine(db.DefaultContext).Where(cond)
if len(opts.LabelIDs) > 0 {
s.Join("INNER", "issue_label", "issue_label.issue_id = issue.id").
In("issue_label.label_id", opts.LabelIDs)
}
if opts.IsArchived != util.OptionalBoolNone {
s.Join("INNER", "repository", "issue.repo_id = repository.id").
And(builder.Eq{"repository.is_archived": opts.IsArchived.IsTrue()})
if opts.UserID > 0 || opts.IsArchived != util.OptionalBoolNone {
s.Join("INNER", "repository", "issue.repo_id = repository.id")
if opts.IsArchived != util.OptionalBoolNone {
s.And(builder.Eq{"repository.is_archived": opts.IsArchived.IsTrue()})
}
}
return s
}
switch opts.FilterMode {
case FilterModeAll:
stats.OpenCount, err = applyReposCondition(sess(cond), opts.UserRepoIDs).
stats.OpenCount, err = sess(cond).
And("issue.is_closed = ?", false).
Count(new(Issue))
if err != nil {
return nil, err
}
stats.ClosedCount, err = applyReposCondition(sess(cond), opts.UserRepoIDs).
stats.ClosedCount, err = sess(cond).
And("issue.is_closed = ?", true).
Count(new(Issue))
if err != nil {
@@ -1768,7 +1816,7 @@ func GetUserIssueStats(opts UserIssueStatsOptions) (*IssueStats, error) {
return nil, err
}
stats.YourRepositoriesCount, err = applyReposCondition(sess(cond), opts.UserRepoIDs).Count(new(Issue))
stats.YourRepositoriesCount, err = sess(cond).Count(new(Issue))
if err != nil {
return nil, err
}