@@ -6,13 +6,15 @@ package issues
6
6
import (
7
7
"context"
8
8
"fmt"
9
+ "strconv"
9
10
"strings"
10
11
11
12
"code.gitea.io/gitea/models/db"
12
13
"code.gitea.io/gitea/models/organization"
13
14
repo_model "code.gitea.io/gitea/models/repo"
14
15
"code.gitea.io/gitea/models/unit"
15
16
user_model "code.gitea.io/gitea/models/user"
17
+ "code.gitea.io/gitea/modules/container"
16
18
"code.gitea.io/gitea/modules/optional"
17
19
18
20
"xorm.io/builder"
@@ -116,14 +118,30 @@ func applyLabelsCondition(sess *xorm.Session, opts *IssuesOptions) {
116
118
if opts .LabelIDs [0 ] == 0 {
117
119
sess .Where ("issue.id NOT IN (SELECT issue_id FROM issue_label)" )
118
120
} else {
119
- for i , labelID := range opts .LabelIDs {
121
+ // We sort and deduplicate the labels' ids
122
+ IncludedLabelIDs := make (container.Set [int64 ])
123
+ ExcludedLabelIDs := make (container.Set [int64 ])
124
+ for _ , labelID := range opts .LabelIDs {
120
125
if labelID > 0 {
121
- sess .Join ("INNER" , fmt .Sprintf ("issue_label il%d" , i ),
122
- fmt .Sprintf ("issue.id = il%[1]d.issue_id AND il%[1]d.label_id = %[2]d" , i , labelID ))
126
+ IncludedLabelIDs .Add (labelID )
123
127
} else if labelID < 0 { // 0 is not supported here, so just ignore it
124
- sess . Where ( "issue.id not in (select issue_id from issue_label where label_id = ?)" , - labelID )
128
+ ExcludedLabelIDs . Add ( - labelID )
125
129
}
126
130
}
131
+ // ... and use them in a subquery of the form :
132
+ // where (select count(*) from issue_label where issue_id=issue.id and label_id in (2, 4, 6)) = 3
133
+ // This equality is guaranteed thanks to unique index (issue_id,label_id) on table issue_label.
134
+ if len (IncludedLabelIDs ) > 0 {
135
+ subquery := builder .Select ("count(*)" ).From ("issue_label" ).Where (builder .Expr ("issue_id = issue.id" )).
136
+ And (builder .In ("label_id" , IncludedLabelIDs .Values ()))
137
+ sess .Where (builder.Eq {strconv .Itoa (len (IncludedLabelIDs )): subquery })
138
+ }
139
+ // or (select count(*)...) = 0 for excluded labels
140
+ if len (ExcludedLabelIDs ) > 0 {
141
+ subquery := builder .Select ("count(*)" ).From ("issue_label" ).Where (builder .Expr ("issue_id = issue.id" )).
142
+ And (builder .In ("label_id" , ExcludedLabelIDs .Values ()))
143
+ sess .Where (builder.Eq {"0" : subquery })
144
+ }
127
145
}
128
146
}
129
147
0 commit comments