internal/store/scope.go

3bcdce33fb9a2309312854331359d376171c7368
gitbay/internal/store/scope.go history · blame · raw

48 lines · 1316 bytes

 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}