mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Use subquery to instead In (#10874)
* Use subquery to instead In * Support excludedLabelNames on issues options * Fix tests Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
		@@ -1045,16 +1045,18 @@ func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) {
 | 
			
		||||
// IssuesOptions represents options of an issue.
 | 
			
		||||
type IssuesOptions struct {
 | 
			
		||||
	ListOptions
 | 
			
		||||
	RepoIDs     []int64 // include all repos if empty
 | 
			
		||||
	AssigneeID  int64
 | 
			
		||||
	PosterID    int64
 | 
			
		||||
	MentionedID int64
 | 
			
		||||
	MilestoneID int64
 | 
			
		||||
	IsClosed    util.OptionalBool
 | 
			
		||||
	IsPull      util.OptionalBool
 | 
			
		||||
	LabelIDs    []int64
 | 
			
		||||
	SortType    string
 | 
			
		||||
	IssueIDs    []int64
 | 
			
		||||
	RepoIDs            []int64 // include all repos if empty
 | 
			
		||||
	AssigneeID         int64
 | 
			
		||||
	PosterID           int64
 | 
			
		||||
	MentionedID        int64
 | 
			
		||||
	MilestoneID        int64
 | 
			
		||||
	IsClosed           util.OptionalBool
 | 
			
		||||
	IsPull             util.OptionalBool
 | 
			
		||||
	LabelIDs           []int64
 | 
			
		||||
	IncludedLabelNames []string
 | 
			
		||||
	ExcludedLabelNames []string
 | 
			
		||||
	SortType           string
 | 
			
		||||
	IssueIDs           []int64
 | 
			
		||||
	// prioritize issues from this repo
 | 
			
		||||
	PriorityRepoID int64
 | 
			
		||||
}
 | 
			
		||||
@@ -1153,6 +1155,14 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.IncludedLabelNames) > 0 {
 | 
			
		||||
		sess.In("issue.id", BuildLabelNamesIssueIDsCondition(opts.IncludedLabelNames))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(opts.ExcludedLabelNames) > 0 {
 | 
			
		||||
		sess.And(builder.NotIn("issue.id", BuildLabelNamesIssueIDsCondition(opts.ExcludedLabelNames)))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CountIssuesByRepo map from repoID to number of issues matching the options
 | 
			
		||||
 
 | 
			
		||||
@@ -269,6 +269,17 @@ func GetLabelIDsInRepoByNames(repoID int64, labelNames []string) ([]int64, error
 | 
			
		||||
		Find(&labelIDs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildLabelNamesIssueIDsCondition returns a builder where get issue ids match label names
 | 
			
		||||
func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
 | 
			
		||||
	return builder.Select("issue_label.issue_id").
 | 
			
		||||
		From("issue_label").
 | 
			
		||||
		InnerJoin("label", "label.id = issue_label.label_id").
 | 
			
		||||
		Where(
 | 
			
		||||
			builder.In("label.name", labelNames),
 | 
			
		||||
		).
 | 
			
		||||
		GroupBy("issue_label.issue_id")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetLabelIDsInReposByNames returns a list of labelIDs by names in one of the given
 | 
			
		||||
// repositories.
 | 
			
		||||
// it silently ignores label names that do not belong to the repository.
 | 
			
		||||
 
 | 
			
		||||
@@ -88,6 +88,7 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
		opts.Private = true
 | 
			
		||||
		opts.AllLimited = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	issueCount := 0
 | 
			
		||||
	for page := 1; ; page++ {
 | 
			
		||||
		opts.Page = page
 | 
			
		||||
@@ -127,15 +128,6 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
		issueIDs, err = issue_indexer.SearchIssuesByKeyword(repoIDs, keyword)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	labels := ctx.Query("labels")
 | 
			
		||||
	if splitted := strings.Split(labels, ","); labels != "" && len(splitted) > 0 {
 | 
			
		||||
		labelIDs, err = models.GetLabelIDsInReposByNames(repoIDs, splitted)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var isPull util.OptionalBool
 | 
			
		||||
	switch ctx.Query("type") {
 | 
			
		||||
	case "pulls":
 | 
			
		||||
@@ -146,6 +138,12 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
		isPull = util.OptionalBoolNone
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	labels := strings.TrimSpace(ctx.Query("labels"))
 | 
			
		||||
	var includedLabelNames []string
 | 
			
		||||
	if len(labels) > 0 {
 | 
			
		||||
		includedLabelNames = strings.Split(labels, ",")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Only fetch the issues if we either don't have a keyword or the search returned issues
 | 
			
		||||
	// This would otherwise return all issues if no issues were found by the search.
 | 
			
		||||
	if len(keyword) == 0 || len(issueIDs) > 0 || len(labelIDs) > 0 {
 | 
			
		||||
@@ -154,13 +152,13 @@ func SearchIssues(ctx *context.APIContext) {
 | 
			
		||||
				Page:     ctx.QueryInt("page"),
 | 
			
		||||
				PageSize: setting.UI.IssuePagingNum,
 | 
			
		||||
			},
 | 
			
		||||
			RepoIDs:        repoIDs,
 | 
			
		||||
			IsClosed:       isClosed,
 | 
			
		||||
			IssueIDs:       issueIDs,
 | 
			
		||||
			LabelIDs:       labelIDs,
 | 
			
		||||
			SortType:       "priorityrepo",
 | 
			
		||||
			PriorityRepoID: ctx.QueryInt64("priority_repo_id"),
 | 
			
		||||
			IsPull:         isPull,
 | 
			
		||||
			RepoIDs:            repoIDs,
 | 
			
		||||
			IsClosed:           isClosed,
 | 
			
		||||
			IssueIDs:           issueIDs,
 | 
			
		||||
			IncludedLabelNames: includedLabelNames,
 | 
			
		||||
			SortType:           "priorityrepo",
 | 
			
		||||
			PriorityRepoID:     ctx.QueryInt64("priority_repo_id"),
 | 
			
		||||
			IsPull:             isPull,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user