@@ -5,6 +5,8 @@ package issues
55
66import (
77 "context"
8+ "slices"
9+ "sort"
810
911 "code.gitea.io/gitea/models/db"
1012 organization_model "code.gitea.io/gitea/models/organization"
@@ -153,43 +155,60 @@ func CountReviews(ctx context.Context, opts FindReviewOptions) (int64, error) {
153155 return db .GetEngine (ctx ).Where (opts .toCond ()).Count (& Review {})
154156}
155157
156- // GetReviewersFromOriginalAuthorsByIssueID gets the latest review of each original authors for a pull request
157- func GetReviewersFromOriginalAuthorsByIssueID (ctx context.Context , issueID int64 ) (ReviewList , error ) {
158+ // GetReviewsByIssueID gets the latest review of each reviewer for a pull request
159+ // The first returned parameter is the latest review of each individual reviewer or team
160+ // The second returned parameter is the latest review of each original author which is migrated from other systems
161+ // The reviews are sorted by updated time
162+ func GetReviewsByIssueID (ctx context.Context , issueID int64 ) (latestReviews , migratedOriginalReviews ReviewList , err error ) {
158163 reviews := make ([]* Review , 0 , 10 )
159164
160- // Get latest review of each reviewer, sorted in order they were made
161- if err := db .GetEngine (ctx ).SQL ("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND original_author_id <> 0 GROUP BY issue_id, original_author_id) ORDER BY review.updated_unix ASC" ,
162- issueID , ReviewTypeApprove , ReviewTypeReject , ReviewTypeRequest ).
163- Find (& reviews ); err != nil {
164- return nil , err
165+ // Get all reviews for the issue id
166+ if err := db .GetEngine (ctx ).Where ("issue_id=?" , issueID ).OrderBy ("updated_unix ASC" ).Find (& reviews ); err != nil {
167+ return nil , nil , err
165168 }
166169
167- return reviews , nil
168- }
169-
170- // GetReviewsByIssueID gets the latest review of each reviewer for a pull request
171- func GetReviewsByIssueID (ctx context.Context , issueID int64 ) (ReviewList , error ) {
172- reviews := make ([]* Review , 0 , 10 )
173-
174- sess := db .GetEngine (ctx )
170+ // filter them in memory to get the latest review of each reviewer
171+ // Since the reviews should not be too many for one issue, less than 100 commonly, it's acceptable to do this in memory
172+ // And since there are too less indexes in review table, it will be very slow to filter in the database
173+ reviewersMap := make (map [int64 ][]* Review ) // key is reviewer id
174+ originalReviewersMap := make (map [int64 ][]* Review ) // key is original author id
175+ reviewTeamsMap := make (map [int64 ][]* Review ) // key is reviewer team id
176+ countedReivewTypes := []ReviewType {ReviewTypeApprove , ReviewTypeReject , ReviewTypeRequest }
177+ for _ , review := range reviews {
178+ if review .ReviewerTeamID == 0 && slices .Contains (countedReivewTypes , review .Type ) && ! review .Dismissed {
179+ if review .OriginalAuthorID != 0 {
180+ originalReviewersMap [review .OriginalAuthorID ] = append (originalReviewersMap [review .OriginalAuthorID ], review )
181+ } else {
182+ reviewersMap [review .ReviewerID ] = append (reviewersMap [review .ReviewerID ], review )
183+ }
184+ } else if review .ReviewerTeamID != 0 && review .OriginalAuthorID == 0 {
185+ reviewTeamsMap [review .ReviewerTeamID ] = append (reviewTeamsMap [review .ReviewerTeamID ], review )
186+ }
187+ }
175188
176- // Get latest review of each reviewer, sorted in order they were made
177- if err := sess .SQL ("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND dismissed = ? AND original_author_id = 0 GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC" ,
178- issueID , ReviewTypeApprove , ReviewTypeReject , ReviewTypeRequest , false ).
179- Find (& reviews ); err != nil {
180- return nil , err
189+ individualReviews := make ([]* Review , 0 , 10 )
190+ for _ , reviews := range reviewersMap {
191+ individualReviews = append (individualReviews , reviews [len (reviews )- 1 ])
181192 }
193+ sort .Slice (individualReviews , func (i , j int ) bool {
194+ return individualReviews [i ].UpdatedUnix < individualReviews [j ].UpdatedUnix
195+ })
182196
183- teamReviewRequests := make ([]* Review , 0 , 5 )
184- if err := sess .SQL ("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id <> 0 AND original_author_id = 0 GROUP BY issue_id, reviewer_team_id) ORDER BY review.updated_unix ASC" ,
185- issueID ).
186- Find (& teamReviewRequests ); err != nil {
187- return nil , err
197+ originalReviews := make ([]* Review , 0 , 10 )
198+ for _ , reviews := range originalReviewersMap {
199+ originalReviews = append (originalReviews , reviews [len (reviews )- 1 ])
188200 }
201+ sort .Slice (originalReviews , func (i , j int ) bool {
202+ return originalReviews [i ].UpdatedUnix < originalReviews [j ].UpdatedUnix
203+ })
189204
190- if len (teamReviewRequests ) > 0 {
191- reviews = append (reviews , teamReviewRequests ... )
205+ teamReviewRequests := make ([]* Review , 0 , 5 )
206+ for _ , reviews := range reviewTeamsMap {
207+ teamReviewRequests = append (teamReviewRequests , reviews [len (reviews )- 1 ])
192208 }
209+ sort .Slice (teamReviewRequests , func (i , j int ) bool {
210+ return teamReviewRequests [i ].UpdatedUnix < teamReviewRequests [j ].UpdatedUnix
211+ })
193212
194- return reviews , nil
213+ return append ( individualReviews , teamReviewRequests ... ), originalReviews , nil
195214}
0 commit comments