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

Optimization of labels handling in issue_search (#26460)

This PR enhances the labels handling in issue_search by optimizing the
SQL query and de-duplicate the IDs when generating the query string.

---------

Co-authored-by: techknowlogick <techknowlogick@gitea.com>
This commit is contained in:
Chl
2024-06-25 19:09:13 +02:00
committed by GitHub
parent 72c66bd479
commit b5326a431f
3 changed files with 59 additions and 9 deletions

View File

@@ -6,6 +6,7 @@ package issues
import (
"context"
"fmt"
"strconv"
"strings"
"code.gitea.io/gitea/models/db"
@@ -13,6 +14,7 @@ import (
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/optional"
"xorm.io/builder"
@@ -116,14 +118,30 @@ func applyLabelsCondition(sess *xorm.Session, opts *IssuesOptions) {
if opts.LabelIDs[0] == 0 {
sess.Where("issue.id NOT IN (SELECT issue_id FROM issue_label)")
} else {
for i, labelID := range opts.LabelIDs {
// We sort and deduplicate the labels' ids
IncludedLabelIDs := make(container.Set[int64])
ExcludedLabelIDs := make(container.Set[int64])
for _, labelID := range opts.LabelIDs {
if labelID > 0 {
sess.Join("INNER", fmt.Sprintf("issue_label il%d", i),
fmt.Sprintf("issue.id = il%[1]d.issue_id AND il%[1]d.label_id = %[2]d", i, labelID))
IncludedLabelIDs.Add(labelID)
} else if labelID < 0 { // 0 is not supported here, so just ignore it
sess.Where("issue.id not in (select issue_id from issue_label where label_id = ?)", -labelID)
ExcludedLabelIDs.Add(-labelID)
}
}
// ... and use them in a subquery of the form :
// where (select count(*) from issue_label where issue_id=issue.id and label_id in (2, 4, 6)) = 3
// This equality is guaranteed thanks to unique index (issue_id,label_id) on table issue_label.
if len(IncludedLabelIDs) > 0 {
subquery := builder.Select("count(*)").From("issue_label").Where(builder.Expr("issue_id = issue.id")).
And(builder.In("label_id", IncludedLabelIDs.Values()))
sess.Where(builder.Eq{strconv.Itoa(len(IncludedLabelIDs)): subquery})
}
// or (select count(*)...) = 0 for excluded labels
if len(ExcludedLabelIDs) > 0 {
subquery := builder.Select("count(*)").From("issue_label").Where(builder.Expr("issue_id = issue.id")).
And(builder.In("label_id", ExcludedLabelIDs.Values()))
sess.Where(builder.Eq{"0": subquery})
}
}
}