this repo has no description
1package db
2
3import (
4 "database/sql"
5 "fmt"
6 "strings"
7
8 "github.com/bluesky-social/indigo/atproto/syntax"
9 "tangled.org/core/api/tangled"
10 "tangled.org/core/appview/models"
11)
12
13// FindReferences resolves refLinks to Issue/PR/IssueComment/PullComment ATURIs.
14// It will ignore missing refLinks.
15func FindReferences(e Execer, refLinks []models.ReferenceLink) ([]syntax.ATURI, error) {
16 var (
17 issueRefs []models.ReferenceLink
18 pullRefs []models.ReferenceLink
19 )
20 for _, ref := range refLinks {
21 switch ref.Kind {
22 case models.RefKindIssue:
23 issueRefs = append(issueRefs, ref)
24 case models.RefKindPull:
25 pullRefs = append(pullRefs, ref)
26 }
27 }
28 issueUris, err := findIssueReferences(e, issueRefs)
29 if err != nil {
30 return nil, err
31 }
32 pullUris, err := findPullReferences(e, pullRefs)
33 if err != nil {
34 return nil, err
35 }
36
37 return append(issueUris, pullUris...), nil
38}
39
40func findIssueReferences(e Execer, refLinks []models.ReferenceLink) ([]syntax.ATURI, error) {
41 if len(refLinks) == 0 {
42 return nil, nil
43 }
44 vals := make([]string, len(refLinks))
45 args := make([]any, 0, len(refLinks)*4)
46 for i, ref := range refLinks {
47 vals[i] = "(?, ?, ?, ?)"
48 args = append(args, ref.Handle, ref.Repo, ref.SubjectId, ref.CommentId)
49 }
50 query := fmt.Sprintf(
51 `with input(owner_did, name, issue_id, comment_id) as (
52 values %s
53 )
54 select
55 i.did, i.rkey,
56 c.did, c.rkey
57 from input inp
58 join repos r
59 on r.did = inp.owner_did
60 and r.name = inp.name
61 join issues i
62 on i.repo_at = r.at_uri
63 and i.issue_id = inp.issue_id
64 left join issue_comments c
65 on inp.comment_id is not null
66 and c.issue_at = i.at_uri
67 and c.id = inp.comment_id
68 `,
69 strings.Join(vals, ","),
70 )
71 rows, err := e.Query(query, args...)
72 if err != nil {
73 return nil, err
74 }
75 defer rows.Close()
76
77 var uris []syntax.ATURI
78
79 for rows.Next() {
80 // Scan rows
81 var issueOwner, issueRkey string
82 var commentOwner, commentRkey sql.NullString
83 var uri syntax.ATURI
84 if err := rows.Scan(&issueOwner, &issueRkey, &commentOwner, &commentRkey); err != nil {
85 return nil, err
86 }
87 if commentOwner.Valid && commentRkey.Valid {
88 uri = syntax.ATURI(fmt.Sprintf(
89 "at://%s/%s/%s",
90 commentOwner.String,
91 tangled.RepoIssueCommentNSID,
92 commentRkey.String,
93 ))
94 } else {
95 uri = syntax.ATURI(fmt.Sprintf(
96 "at://%s/%s/%s",
97 issueOwner,
98 tangled.RepoIssueNSID,
99 issueRkey,
100 ))
101 }
102 uris = append(uris, uri)
103 }
104 return uris, nil
105}
106
107func findPullReferences(e Execer, refLinks []models.ReferenceLink) ([]syntax.ATURI, error) {
108 if len(refLinks) == 0 {
109 return nil, nil
110 }
111 vals := make([]string, len(refLinks))
112 args := make([]any, 0, len(refLinks)*4)
113 for i, ref := range refLinks {
114 vals[i] = "(?, ?, ?, ?)"
115 args = append(args, ref.Handle, ref.Repo, ref.SubjectId, ref.CommentId)
116 }
117 query := fmt.Sprintf(
118 `with input(owner_did, name, pull_id, comment_id) as (
119 values %s
120 )
121 select
122 p.owner_did, p.rkey,
123 c.owner_did, c.rkey
124 from input inp
125 join repos r
126 on r.did = inp.owner_did
127 and r.name = inp.name
128 join pulls p
129 on p.repo_at = r.at_uri
130 and p.pull_id = inp.pull_id
131 left join pull_comments c
132 on inp.comment_id is not null
133 and c.repo_at = r.at_uri and c.pull_id = p.pull_id
134 and c.id = inp.comment_id
135 `,
136 strings.Join(vals, ","),
137 )
138 rows, err := e.Query(query, args...)
139 if err != nil {
140 return nil, err
141 }
142 defer rows.Close()
143
144 var uris []syntax.ATURI
145
146 for rows.Next() {
147 // Scan rows
148 var pullOwner, pullRkey string
149 var commentOwner, commentRkey sql.NullString
150 var uri syntax.ATURI
151 if err := rows.Scan(&pullOwner, &pullRkey, &commentOwner, &commentRkey); err != nil {
152 return nil, err
153 }
154 if commentOwner.Valid && commentRkey.Valid {
155 uri = syntax.ATURI(fmt.Sprintf(
156 "at://%s/%s/%s",
157 commentOwner.String,
158 tangled.RepoPullCommentNSID,
159 commentRkey.String,
160 ))
161 } else {
162 uri = syntax.ATURI(fmt.Sprintf(
163 "at://%s/%s/%s",
164 pullOwner,
165 tangled.RepoPullNSID,
166 pullRkey,
167 ))
168 }
169 uris = append(uris, uri)
170 }
171 return uris, nil
172}