| @@ -45,33 +45,39 @@ func (s *Store) dashboardQuery(q string, userID int64) ([]DashboardItem, error) |
| 45 | 45 | return out, rows.Err() |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | // The dashboard's four list queries are named so the plan test can assert |
| 49 | // each still walks the 0035 index that supplies its ORDER BY. |
| 50 | const dashboardMRsQuery = ` |
| 51 | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 52 | x.number, x.title, au.username, x.state, x.updated_at |
| 53 | FROM merge_requests x |
| 54 | JOIN repos r ON r.id = x.repo_id |
| 55 | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 56 | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 57 | JOIN users au ON au.id = x.author_id |
| 58 | WHERE x.state IN ('open', 'source_gone') AND ` + involvedCond + ` |
| 59 | ORDER BY x.updated_at DESC LIMIT 50` |
| 60 | |
| 48 | 61 | // DashboardMRs returns open merge requests involving the user: on their |
| 49 | 62 | // repositories (owned, granted, org) or authored by them anywhere. |
| 50 | 63 | func (s *Store) DashboardMRs(userID int64) ([]DashboardItem, error) { |
| 51 | | return s.dashboardQuery(` |
| 52 | | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 53 | | x.number, x.title, au.username, x.state, x.updated_at |
| 54 | | FROM merge_requests x |
| 55 | | JOIN repos r ON r.id = x.repo_id |
| 56 | | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 57 | | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 58 | | JOIN users au ON au.id = x.author_id |
| 59 | | WHERE x.state IN ('open', 'source_gone') AND `+involvedCond+` |
| 60 | | ORDER BY x.updated_at DESC LIMIT 50`, userID) |
| 64 | return s.dashboardQuery(dashboardMRsQuery, userID) |
| 61 | 65 | } |
| 62 | 66 | |
| 63 | 67 | // DashboardIssues is the issue counterpart of DashboardMRs. |
| 68 | const dashboardIssuesQuery = ` |
| 69 | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 70 | x.number, x.title, au.username, x.state, x.updated_at |
| 71 | FROM issues x |
| 72 | JOIN repos r ON r.id = x.repo_id |
| 73 | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 74 | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 75 | JOIN users au ON au.id = x.author_id |
| 76 | WHERE x.state = 'open' AND ` + involvedCond + ` |
| 77 | ORDER BY x.updated_at DESC LIMIT 50` |
| 78 | |
| 64 | 79 | func (s *Store) DashboardIssues(userID int64) ([]DashboardItem, error) { |
| 65 | | return s.dashboardQuery(` |
| 66 | | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 67 | | x.number, x.title, au.username, x.state, x.updated_at |
| 68 | | FROM issues x |
| 69 | | JOIN repos r ON r.id = x.repo_id |
| 70 | | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 71 | | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 72 | | JOIN users au ON au.id = x.author_id |
| 73 | | WHERE x.state = 'open' AND `+involvedCond+` |
| 74 | | ORDER BY x.updated_at DESC LIMIT 50`, userID) |
| 80 | return s.dashboardQuery(dashboardIssuesQuery, userID) |
| 75 | 81 | } |
| 76 | 82 | |
| 77 | 83 | func (s *Store) PinRepo(userID, repoID int64) error { |
| @@ -124,22 +130,24 @@ func (s *Store) PinnedRepos(userID int64) ([]Repo, error) { |
| 124 | 130 | // ReviewQueue returns open merge requests the user is involved in, has not |
| 125 | 131 | // authored, and has not reviewed at the current head — what the rail shows |
| 126 | 132 | // as waiting on them. Ordered most recently touched first. |
| 133 | const reviewQueueQuery = ` |
| 134 | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 135 | x.number, x.title, au.username, x.state, x.updated_at |
| 136 | FROM merge_requests x |
| 137 | JOIN repos r ON r.id = x.repo_id |
| 138 | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 139 | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 140 | JOIN users au ON au.id = x.author_id |
| 141 | WHERE x.state IN ('open', 'source_gone') |
| 142 | AND x.author_id <> ?1 |
| 143 | AND NOT EXISTS (SELECT 1 FROM mr_reviews rv |
| 144 | WHERE rv.mr_id = x.id AND rv.reviewer_id = ?1 |
| 145 | AND rv.head_sha = x.head_sha) |
| 146 | AND ` + involvedCond + ` |
| 147 | ORDER BY x.updated_at DESC LIMIT 8` |
| 148 | |
| 127 | 149 | func (s *Store) ReviewQueue(userID int64) ([]DashboardItem, error) { |
| 128 | | return s.dashboardQuery(` |
| 129 | | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 130 | | x.number, x.title, au.username, x.state, x.updated_at |
| 131 | | FROM merge_requests x |
| 132 | | JOIN repos r ON r.id = x.repo_id |
| 133 | | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 134 | | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 135 | | JOIN users au ON au.id = x.author_id |
| 136 | | WHERE x.state IN ('open', 'source_gone') |
| 137 | | AND x.author_id <> ?1 |
| 138 | | AND NOT EXISTS (SELECT 1 FROM mr_reviews rv |
| 139 | | WHERE rv.mr_id = x.id AND rv.reviewer_id = ?1 |
| 140 | | AND rv.head_sha = x.head_sha) |
| 141 | | AND `+involvedCond+` |
| 142 | | ORDER BY x.updated_at DESC LIMIT 8`, userID) |
| 150 | return s.dashboardQuery(reviewQueueQuery, userID) |
| 143 | 151 | } |
| 144 | 152 | |
| 145 | 153 | // OpenCounts returns the repo's open issue and open merge request counts, |
| @@ -155,19 +163,24 @@ func (s *Store) OpenCounts(repoID int64) (issues, mrs int) { |
| 155 | 163 | // AssignedIssues returns open issues assigned to the user, wherever they |
| 156 | 164 | // live. Assignment is a direct request for someone's attention, so it is |
| 157 | 165 | // not narrowed by the involvement rule the other lists use. |
| 166 | // |
| 167 | // It drives from issue_assignees rather than testing EXISTS against every |
| 168 | // issue: the assignee rows for one user are a handful, the issues table |
| 169 | // is the whole instance. |
| 170 | const assignedIssuesQuery = ` |
| 171 | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 172 | x.number, x.title, au.username, x.state, x.updated_at |
| 173 | FROM issue_assignees ia |
| 174 | JOIN issues x ON x.id = ia.issue_id |
| 175 | JOIN repos r ON r.id = x.repo_id |
| 176 | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 177 | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 178 | JOIN users au ON au.id = x.author_id |
| 179 | WHERE ia.user_id = ?1 AND x.state = 'open' |
| 180 | ORDER BY x.updated_at DESC LIMIT 20` |
| 181 | |
| 158 | 182 | func (s *Store) AssignedIssues(userID int64) ([]DashboardItem, error) { |
| 159 | | return s.dashboardQuery(` |
| 160 | | SELECT COALESCE(u.username, o.name) || '/' || r.name, |
| 161 | | x.number, x.title, au.username, x.state, x.updated_at |
| 162 | | FROM issues x |
| 163 | | JOIN repos r ON r.id = x.repo_id |
| 164 | | LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id |
| 165 | | LEFT JOIN orgs o ON r.owner_kind = 'org' AND o.id = r.owner_id |
| 166 | | JOIN users au ON au.id = x.author_id |
| 167 | | WHERE x.state = 'open' |
| 168 | | AND EXISTS (SELECT 1 FROM issue_assignees ia |
| 169 | | WHERE ia.issue_id = x.id AND ia.user_id = ?1) |
| 170 | | ORDER BY x.updated_at DESC LIMIT 20`, userID) |
| 183 | return s.dashboardQuery(assignedIssuesQuery, userID) |
| 171 | 184 | } |
| 172 | 185 | |
| 173 | 186 | // DashboardBuild is one build row on the dashboard, with its repo resolved. |