internal/store/scope.go
48 lines · 1316 bytes
4 symbols in this file
1package store
2
3import (
4 "database/sql"
5 "errors"
6 "strings"
7)
8
9// ErrOrgScoped is returned when a repository-level write names a label or
10// milestone its org holds; the org commands manage those.
11var ErrOrgScoped = errors.New("held by the org")
12
13// scopeClause selects the label or milestone rows a repository sees: its
14// own, and its org's when an org owns it. alias is the table alias in the
15// query.
16func scopeClause(alias string, repo Repo) (string, []any) {
17 if repo.OwnerKind == "org" {
18 return "(" + alias + ".repo_id = ? OR " + alias + ".org_id = ?)", []any{repo.ID, repo.OwnerID}
19 }
20 return alias + ".repo_id = ?", []any{repo.ID}
21}
22
23// inClause renders ids as a parenthesised placeholder list. An empty set
24// yields (NULL), which matches nothing.
25func inClause(ids []int64) (string, []any) {
26 if len(ids) == 0 {
27 return "(NULL)", nil
28 }
29 args := make([]any, len(ids))
30 for i, id := range ids {
31 args[i] = id
32 }
33 return "(" + strings.TrimSuffix(strings.Repeat("?,", len(ids)), ",") + ")", args
34}
35
36// scanIDs collects a single-column id result and closes the rows.
37func scanIDs(rows *sql.Rows) ([]int64, error) {
38 defer rows.Close()
39 var out []int64
40 for rows.Next() {
41 var id int64
42 if err := rows.Scan(&id); err != nil {
43 return nil, err
44 }
45 out = append(out, id)
46 }
47 return out, rows.Err()
48}