internal/store/search.go

e91fdfe0cc2f9bfdcf99bf1a316d219bed8e2ebf
gitbay/internal/store/search.go history · blame · raw

66 lines · 2298 bytes

 1package store
 2
 3// Search across repositories, for the `search` command and the web's
 4// /search page. Visibility is the same rule everywhere: public plus what
 5// the user reaches, so an anonymous caller (user id 0) sees only public
 6// rows rather than a different query.
 7
 8// visibleCond admits public repositories and anything the user reaches.
 9const visibleCond = `(r.visibility = 'public' OR ` + reachableCond + `)`
10
11// VisibleRepos returns every repository the user may read, public ones
12// included, ordered by owner then name.
13func (s *Store) VisibleRepos(userID int64) ([]Repo, error) {
14	rows, err := s.DB.Query(repoSelect+" WHERE "+visibleCond+" ORDER BY 4, r.name", userID)
15	if err != nil {
16		return nil, err
17	}
18	defer rows.Close()
19	var out []Repo
20	for rows.Next() {
21		r, err := scanRepo(rows)
22		if err != nil {
23			return nil, err
24		}
25		out = append(out, r)
26	}
27	return out, rows.Err()
28}
29
30// SearchIssues returns issues matching q in title or body, newest
31// activity first.
32func (s *Store) SearchIssues(userID int64, q string, limit int) ([]DashboardItem, error) {
33	return s.searchQuery("issues", "issue_fts", userID, q, limit)
34}
35
36// SearchMRs is SearchIssues for merge requests.
37func (s *Store) SearchMRs(userID int64, q string, limit int) ([]DashboardItem, error) {
38	return s.searchQuery("merge_requests", "mr_fts", userID, q, limit)
39}
40
41func (s *Store) searchQuery(table, index string, userID int64, q string, limit int) ([]DashboardItem, error) {
42	rows, err := s.DB.Query(`
43		SELECT COALESCE(u.username, o.name) || '/' || r.name,
44		       x.number, x.title, au.username, x.state, x.updated_at
45		FROM `+table+` x
46		JOIN repos r ON r.id = x.repo_id
47		LEFT JOIN users u ON r.owner_kind = 'user' AND u.id = r.owner_id
48		LEFT JOIN orgs o  ON r.owner_kind = 'org'  AND o.id = r.owner_id
49		JOIN users au ON au.id = x.author_id
50		WHERE x.id IN (SELECT rowid FROM `+index+` WHERE `+index+` MATCH ?2)
51		  AND `+visibleCond+`
52		ORDER BY x.updated_at DESC LIMIT ?3`, userID, FTSQuery(q), limit)
53	if err != nil {
54		return nil, err
55	}
56	defer rows.Close()
57	var out []DashboardItem
58	for rows.Next() {
59		var d DashboardItem
60		if err := rows.Scan(&d.RepoPath, &d.Number, &d.Title, &d.Author, &d.State, &d.UpdatedAt); err != nil {
61			return nil, err
62		}
63		out = append(out, d)
64	}
65	return out, rows.Err()
66}