Monorepo for Tangled

[WIP] appview/db: update query functions for repo_did across all tables

+341 -82
+14 -1
appview/db/artifact.go
··· 1 package db 2 3 import ( 4 "fmt" 5 "strings" 6 "time" ··· 12 ) 13 14 func AddArtifact(e Execer, artifact models.Artifact) error { 15 _, err := e.Exec( 16 `insert or ignore into artifacts ( 17 did, 18 rkey, 19 repo_at, 20 tag, 21 created, 22 blob_cid, ··· 24 size, 25 mimetype 26 ) 27 - values (?, ?, ?, ?, ?, ?, ?, ?, ?)`, 28 artifact.Did, 29 artifact.Rkey, 30 artifact.RepoAt, 31 artifact.Tag[:], 32 artifact.CreatedAt.Format(time.RFC3339), 33 artifact.BlobCid.String(), ··· 57 did, 58 rkey, 59 repo_at, 60 tag, 61 created, 62 blob_cid, ··· 78 var createdAt string 79 var tag []byte 80 var blobCid string 81 82 if err := rows.Scan( 83 &artifact.Did, 84 &artifact.Rkey, 85 &artifact.RepoAt, 86 &tag, 87 &createdAt, 88 &blobCid, ··· 91 &artifact.MimeType, 92 ); err != nil { 93 return nil, err 94 } 95 96 artifact.CreatedAt, err = time.Parse(time.RFC3339, createdAt)
··· 1 package db 2 3 import ( 4 + "database/sql" 5 "fmt" 6 "strings" 7 "time" ··· 13 ) 14 15 func AddArtifact(e Execer, artifact models.Artifact) error { 16 + var repoDid *string 17 + if artifact.RepoDid != "" { 18 + repoDid = &artifact.RepoDid 19 + } 20 _, err := e.Exec( 21 `insert or ignore into artifacts ( 22 did, 23 rkey, 24 repo_at, 25 + repo_did, 26 tag, 27 created, 28 blob_cid, ··· 30 size, 31 mimetype 32 ) 33 + values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 34 artifact.Did, 35 artifact.Rkey, 36 artifact.RepoAt, 37 + repoDid, 38 artifact.Tag[:], 39 artifact.CreatedAt.Format(time.RFC3339), 40 artifact.BlobCid.String(), ··· 64 did, 65 rkey, 66 repo_at, 67 + repo_did, 68 tag, 69 created, 70 blob_cid, ··· 86 var createdAt string 87 var tag []byte 88 var blobCid string 89 + var repoDid sql.NullString 90 91 if err := rows.Scan( 92 &artifact.Did, 93 &artifact.Rkey, 94 &artifact.RepoAt, 95 + &repoDid, 96 &tag, 97 &createdAt, 98 &blobCid, ··· 101 &artifact.MimeType, 102 ); err != nil { 103 return nil, err 104 + } 105 + if repoDid.Valid { 106 + artifact.RepoDid = repoDid.String 107 } 108 109 artifact.CreatedAt, err = time.Parse(time.RFC3339, createdAt)
+15 -3
appview/db/collaborators.go
··· 1 package db 2 3 import ( 4 "fmt" 5 "strings" 6 "time" ··· 10 ) 11 12 func AddCollaborator(e Execer, c models.Collaborator) error { 13 _, err := e.Exec( 14 - `insert into collaborators (did, rkey, subject_did, repo_at) values (?, ?, ?, ?);`, 15 - c.Did, c.Rkey, c.SubjectDid, c.RepoAt, 16 ) 17 return err 18 } ··· 80 rkey, 81 subject_did, 82 repo_at, 83 - created 84 from collaborators %s`, 85 whereClause, 86 ) ··· 92 for rows.Next() { 93 var collaborator models.Collaborator 94 var createdAt string 95 if err := rows.Scan( 96 &collaborator.Id, 97 &collaborator.Did, ··· 99 &collaborator.SubjectDid, 100 &collaborator.RepoAt, 101 &createdAt, 102 ); err != nil { 103 return nil, err 104 } 105 collaborator.Created, err = time.Parse(time.RFC3339, createdAt) 106 if err != nil { 107 collaborator.Created = time.Now() 108 } 109 collaborators = append(collaborators, collaborator) 110 }
··· 1 package db 2 3 import ( 4 + "database/sql" 5 "fmt" 6 "strings" 7 "time" ··· 11 ) 12 13 func AddCollaborator(e Execer, c models.Collaborator) error { 14 + var repoDid *string 15 + if c.RepoDid != "" { 16 + repoDid = &c.RepoDid 17 + } 18 + 19 _, err := e.Exec( 20 + `insert into collaborators (did, rkey, subject_did, repo_at, repo_did) values (?, ?, ?, ?, ?);`, 21 + c.Did, c.Rkey, c.SubjectDid, c.RepoAt, repoDid, 22 ) 23 return err 24 } ··· 86 rkey, 87 subject_did, 88 repo_at, 89 + created, 90 + repo_did 91 from collaborators %s`, 92 whereClause, 93 ) ··· 99 for rows.Next() { 100 var collaborator models.Collaborator 101 var createdAt string 102 + var collabRepoDid sql.NullString 103 if err := rows.Scan( 104 &collaborator.Id, 105 &collaborator.Did, ··· 107 &collaborator.SubjectDid, 108 &collaborator.RepoAt, 109 &createdAt, 110 + &collabRepoDid, 111 ); err != nil { 112 return nil, err 113 } 114 collaborator.Created, err = time.Parse(time.RFC3339, createdAt) 115 if err != nil { 116 collaborator.Created = time.Now() 117 + } 118 + if collabRepoDid.Valid { 119 + collaborator.RepoDid = collabRepoDid.String 120 } 121 collaborators = append(collaborators, collaborator) 122 }
+28 -10
appview/db/issues.go
··· 17 ) 18 19 func PutIssue(tx *sql.Tx, issue *models.Issue) error { 20 - // ensure sequence exists 21 _, err := tx.Exec(` 22 - insert or ignore into repo_issue_seqs (repo_at, next_issue_id) 23 - values (?, 1) 24 - `, issue.RepoAt) 25 if err != nil { 26 return err 27 } ··· 64 return err 65 } 66 67 // insert new issue 68 row := tx.QueryRow(` 69 - insert into issues (repo_at, did, rkey, issue_id, title, body) 70 - values (?, ?, ?, ?, ?, ?) 71 returning rowid, issue_id 72 - `, issue.RepoAt, issue.Did, issue.Rkey, newIssueId, issue.Title, issue.Body) 73 74 err = row.Scan(&issue.Id, &issue.IssueId) 75 if err != nil { ··· 83 } 84 85 func updateIssue(tx *sql.Tx, issue *models.Issue) error { 86 - // update existing issue 87 _, err := tx.Exec(` 88 update issues 89 - set title = ?, body = ?, edited = ? 90 where did = ? and rkey = ? 91 - `, issue.Title, issue.Body, time.Now().Format(time.RFC3339), issue.Did, issue.Rkey) 92 if err != nil { 93 return err 94 } ··· 133 did, 134 rkey, 135 repo_at, 136 issue_id, 137 title, 138 body, ··· 161 var issue models.Issue 162 var createdAt string 163 var editedAt, deletedAt sql.Null[string] 164 var rowNum int64 165 err := rows.Scan( 166 &issue.Id, 167 &issue.Did, 168 &issue.Rkey, 169 &issue.RepoAt, 170 &issue.IssueId, 171 &issue.Title, 172 &issue.Body, ··· 178 ) 179 if err != nil { 180 return nil, fmt.Errorf("failed to scan issue: %w", err) 181 } 182 183 if t, err := time.Parse(time.RFC3339, createdAt); err == nil {
··· 17 ) 18 19 func PutIssue(tx *sql.Tx, issue *models.Issue) error { 20 + var seqRepoDid *string 21 + if issue.RepoDid != "" { 22 + seqRepoDid = &issue.RepoDid 23 + } 24 _, err := tx.Exec(` 25 + insert into repo_issue_seqs (repo_at, next_issue_id, repo_did) 26 + values (?, 1, ?) 27 + on conflict(repo_at) do update set repo_did = coalesce(excluded.repo_did, repo_did) 28 + `, issue.RepoAt, seqRepoDid) 29 if err != nil { 30 return err 31 } ··· 68 return err 69 } 70 71 + var repoDid *string 72 + if issue.RepoDid != "" { 73 + repoDid = &issue.RepoDid 74 + } 75 + 76 // insert new issue 77 row := tx.QueryRow(` 78 + insert into issues (repo_at, repo_did, did, rkey, issue_id, title, body) 79 + values (?, ?, ?, ?, ?, ?, ?) 80 returning rowid, issue_id 81 + `, issue.RepoAt, repoDid, issue.Did, issue.Rkey, newIssueId, issue.Title, issue.Body) 82 83 err = row.Scan(&issue.Id, &issue.IssueId) 84 if err != nil { ··· 92 } 93 94 func updateIssue(tx *sql.Tx, issue *models.Issue) error { 95 + var repoDid *string 96 + if issue.RepoDid != "" { 97 + repoDid = &issue.RepoDid 98 + } 99 _, err := tx.Exec(` 100 update issues 101 + set title = ?, body = ?, edited = ?, repo_did = coalesce(?, repo_did) 102 where did = ? and rkey = ? 103 + `, issue.Title, issue.Body, time.Now().Format(time.RFC3339), repoDid, issue.Did, issue.Rkey) 104 if err != nil { 105 return err 106 } ··· 145 did, 146 rkey, 147 repo_at, 148 + repo_did, 149 issue_id, 150 title, 151 body, ··· 174 var issue models.Issue 175 var createdAt string 176 var editedAt, deletedAt sql.Null[string] 177 + var nullableRepoDid sql.NullString 178 var rowNum int64 179 err := rows.Scan( 180 &issue.Id, 181 &issue.Did, 182 &issue.Rkey, 183 &issue.RepoAt, 184 + &nullableRepoDid, 185 &issue.IssueId, 186 &issue.Title, 187 &issue.Body, ··· 193 ) 194 if err != nil { 195 return nil, fmt.Errorf("failed to scan issue: %w", err) 196 + } 197 + if nullableRepoDid.Valid { 198 + issue.RepoDid = nullableRepoDid.String 199 } 200 201 if t, err := time.Parse(time.RFC3339, createdAt); err == nil {
+13 -3
appview/db/language.go
··· 24 } 25 26 query := fmt.Sprintf( 27 - `select id, repo_at, ref, is_default_ref, language, bytes from repo_languages %s`, 28 whereClause, 29 ) 30 rows, err := e.Query(query, args...) ··· 37 for rows.Next() { 38 var rl models.RepoLanguage 39 var isDefaultRef int 40 41 err := rows.Scan( 42 &rl.Id, ··· 45 &isDefaultRef, 46 &rl.Language, 47 &rl.Bytes, 48 ) 49 if err != nil { 50 return nil, fmt.Errorf("failed to scan: %w ", err) ··· 53 if isDefaultRef != 0 { 54 rl.IsDefaultRef = true 55 } 56 57 langs = append(langs, rl) 58 } ··· 65 66 func InsertRepoLanguages(e Execer, langs []models.RepoLanguage) error { 67 stmt, err := e.Prepare( 68 - "insert or replace into repo_languages (repo_at, ref, is_default_ref, language, bytes) values (?, ?, ?, ?, ?)", 69 ) 70 if err != nil { 71 return err ··· 77 isDefaultRef = 1 78 } 79 80 - _, err := stmt.Exec(l.RepoAt, l.Ref, isDefaultRef, l.Language, l.Bytes) 81 if err != nil { 82 return err 83 }
··· 24 } 25 26 query := fmt.Sprintf( 27 + `select id, repo_at, ref, is_default_ref, language, bytes, repo_did from repo_languages %s`, 28 whereClause, 29 ) 30 rows, err := e.Query(query, args...) ··· 37 for rows.Next() { 38 var rl models.RepoLanguage 39 var isDefaultRef int 40 + var langRepoDid sql.NullString 41 42 err := rows.Scan( 43 &rl.Id, ··· 46 &isDefaultRef, 47 &rl.Language, 48 &rl.Bytes, 49 + &langRepoDid, 50 ) 51 if err != nil { 52 return nil, fmt.Errorf("failed to scan: %w ", err) ··· 55 if isDefaultRef != 0 { 56 rl.IsDefaultRef = true 57 } 58 + if langRepoDid.Valid { 59 + rl.RepoDid = langRepoDid.String 60 + } 61 62 langs = append(langs, rl) 63 } ··· 70 71 func InsertRepoLanguages(e Execer, langs []models.RepoLanguage) error { 72 stmt, err := e.Prepare( 73 + "insert or replace into repo_languages (repo_at, ref, is_default_ref, language, bytes, repo_did) values (?, ?, ?, ?, ?, ?)", 74 ) 75 if err != nil { 76 return err ··· 82 isDefaultRef = 1 83 } 84 85 + var repoDid *string 86 + if l.RepoDid != "" { 87 + repoDid = &l.RepoDid 88 + } 89 + 90 + _, err := stmt.Exec(l.RepoAt, l.Ref, isDefaultRef, l.Language, l.Bytes, repoDid) 91 if err != nil { 92 return err 93 }
+21 -2
appview/db/pipeline.go
··· 1 package db 2 3 import ( 4 "fmt" 5 "slices" 6 "strings" ··· 26 whereClause = " where " + strings.Join(conditions, " and ") 27 } 28 29 - query := fmt.Sprintf(`select id, rkey, knot, repo_owner, repo_name, sha, created from pipelines %s`, whereClause) 30 31 rows, err := e.Query(query, args...) 32 ··· 38 for rows.Next() { 39 var pipeline models.Pipeline 40 var createdAt string 41 err = rows.Scan( 42 &pipeline.Id, 43 &pipeline.Rkey, ··· 46 &pipeline.RepoName, 47 &pipeline.Sha, 48 &createdAt, 49 ) 50 if err != nil { 51 return nil, err ··· 54 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 55 pipeline.Created = t 56 } 57 58 pipelines = append(pipelines, pipeline) 59 } ··· 66 } 67 68 func AddPipeline(e Execer, pipeline models.Pipeline) error { 69 args := []any{ 70 pipeline.Rkey, 71 pipeline.Knot, ··· 73 pipeline.RepoName, 74 pipeline.TriggerId, 75 pipeline.Sha, 76 } 77 78 placeholders := make([]string, len(args)) ··· 87 repo_owner, 88 repo_name, 89 trigger_id, 90 - sha 91 ) values (%s) 92 `, strings.Join(placeholders, ",")) 93 ··· 195 p.repo_name, 196 p.sha, 197 p.created, 198 t.id, 199 t.kind, 200 t.push_ref, ··· 224 var p models.Pipeline 225 var t models.Trigger 226 var created string 227 228 err := rows.Scan( 229 &p.Id, ··· 233 &p.RepoName, 234 &p.Sha, 235 &created, 236 &p.TriggerId, 237 &t.Kind, 238 &t.PushRef, ··· 250 p.Created, err = time.Parse(time.RFC3339, created) 251 if err != nil { 252 return nil, fmt.Errorf("invalid pipeline created timestamp %q: %w", created, err) 253 } 254 255 t.Id = p.TriggerId
··· 1 package db 2 3 import ( 4 + "database/sql" 5 "fmt" 6 "slices" 7 "strings" ··· 27 whereClause = " where " + strings.Join(conditions, " and ") 28 } 29 30 + query := fmt.Sprintf(`select id, rkey, knot, repo_owner, repo_name, sha, created, repo_did from pipelines %s`, whereClause) 31 32 rows, err := e.Query(query, args...) 33 ··· 39 for rows.Next() { 40 var pipeline models.Pipeline 41 var createdAt string 42 + var repoDid sql.NullString 43 err = rows.Scan( 44 &pipeline.Id, 45 &pipeline.Rkey, ··· 48 &pipeline.RepoName, 49 &pipeline.Sha, 50 &createdAt, 51 + &repoDid, 52 ) 53 if err != nil { 54 return nil, err ··· 57 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 58 pipeline.Created = t 59 } 60 + if repoDid.Valid { 61 + pipeline.RepoDid = repoDid.String 62 + } 63 64 pipelines = append(pipelines, pipeline) 65 } ··· 72 } 73 74 func AddPipeline(e Execer, pipeline models.Pipeline) error { 75 + var repoDid *string 76 + if pipeline.RepoDid != "" { 77 + repoDid = &pipeline.RepoDid 78 + } 79 + 80 args := []any{ 81 pipeline.Rkey, 82 pipeline.Knot, ··· 84 pipeline.RepoName, 85 pipeline.TriggerId, 86 pipeline.Sha, 87 + repoDid, 88 } 89 90 placeholders := make([]string, len(args)) ··· 99 repo_owner, 100 repo_name, 101 trigger_id, 102 + sha, 103 + repo_did 104 ) values (%s) 105 `, strings.Join(placeholders, ",")) 106 ··· 208 p.repo_name, 209 p.sha, 210 p.created, 211 + p.repo_did, 212 t.id, 213 t.kind, 214 t.push_ref, ··· 238 var p models.Pipeline 239 var t models.Trigger 240 var created string 241 + var repoDid sql.NullString 242 243 err := rows.Scan( 244 &p.Id, ··· 248 &p.RepoName, 249 &p.Sha, 250 &created, 251 + &repoDid, 252 &p.TriggerId, 253 &t.Kind, 254 &t.PushRef, ··· 266 p.Created, err = time.Parse(time.RFC3339, created) 267 if err != nil { 268 return nil, fmt.Errorf("invalid pipeline created timestamp %q: %w", created, err) 269 + } 270 + if repoDid.Valid { 271 + p.RepoDid = repoDid.String 272 } 273 274 t.Id = p.TriggerId
+6 -3
appview/db/profile.go
··· 75 // TODO: get this in the original query; requires COALESCE because nullable 76 var sourceRepo *models.Repo 77 if repo.Source != "" { 78 - sourceRepo, err = GetRepoByAtUri(e, repo.Source) 79 if err != nil { 80 - // the source repo was not found, skip this bit 81 log.Println("profile", "err", err) 82 } 83 } ··· 449 query = `select count(id) from repos where did = ?` 450 args = append(args, did) 451 case models.VanityStatStarCount: 452 - query = `select count(id) from stars where subject_at like 'at://' || ? || '%'` 453 args = append(args, did) 454 case models.VanityStatNone: 455 return 0, nil
··· 75 // TODO: get this in the original query; requires COALESCE because nullable 76 var sourceRepo *models.Repo 77 if repo.Source != "" { 78 + if strings.HasPrefix(repo.Source, "did:") { 79 + sourceRepo, err = GetRepoByDid(e, repo.Source) 80 + } else { 81 + sourceRepo, err = GetRepoByAtUri(e, repo.Source) 82 + } 83 if err != nil { 84 log.Println("profile", "err", err) 85 } 86 } ··· 452 query = `select count(id) from repos where did = ?` 453 args = append(args, did) 454 case models.VanityStatStarCount: 455 + query = `select count(s.id) from stars s join repos r on (s.subject_at = r.at_uri or (s.subject_did is not null and s.subject_did = r.repo_did)) where r.did = ?` 456 args = append(args, did) 457 case models.VanityStatNone: 458 return 0, nil
+57 -12
appview/db/pulls.go
··· 18 ) 19 20 func NewPull(tx *sql.Tx, pull *models.Pull) error { 21 _, err := tx.Exec(` 22 - insert or ignore into repo_pull_seqs (repo_at, next_pull_id) 23 - values (?, 1) 24 - `, pull.RepoAt) 25 if err != nil { 26 return err 27 } ··· 40 pull.PullId = nextId 41 pull.State = models.PullOpen 42 43 - var sourceBranch, sourceRepoAt *string 44 if pull.PullSource != nil { 45 sourceBranch = &pull.PullSource.Branch 46 if pull.PullSource.RepoAt != nil { 47 x := pull.PullSource.RepoAt.String() 48 sourceRepoAt = &x 49 } 50 } 51 52 var stackId, changeId, parentChangeId *string ··· 63 result, err := tx.Exec( 64 ` 65 insert into pulls ( 66 - repo_at, owner_did, pull_id, title, target_branch, body, rkey, state, source_branch, source_repo_at, stack_id, change_id, parent_change_id 67 ) 68 - values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 69 pull.RepoAt, 70 pull.OwnerDid, 71 pull.PullId, ··· 79 stackId, 80 changeId, 81 parentChangeId, 82 ) 83 if err != nil { 84 return err ··· 159 source_repo_at, 160 stack_id, 161 change_id, 162 - parent_change_id 163 from 164 pulls 165 %s ··· 177 for rows.Next() { 178 var pull models.Pull 179 var createdAt string 180 - var sourceBranch, sourceRepoAt, stackId, changeId, parentChangeId sql.NullString 181 err := rows.Scan( 182 &pull.ID, 183 &pull.OwnerDid, ··· 194 &stackId, 195 &changeId, 196 &parentChangeId, 197 ) 198 if err != nil { 199 return nil, err ··· 216 } 217 pull.PullSource.RepoAt = &sourceRepoAtParsed 218 } 219 } 220 221 if stackId.Valid { ··· 227 if parentChangeId.Valid { 228 pull.ParentChangeId = parentChangeId.String 229 } 230 231 pulls[pull.AtUri()] = &pull 232 } ··· 441 owner_did, 442 comment_at, 443 body, 444 - created 445 from 446 pull_comments 447 %s ··· 459 for rows.Next() { 460 var comment models.PullComment 461 var createdAt string 462 err := rows.Scan( 463 &comment.ID, 464 &comment.PullId, ··· 468 &comment.CommentAt, 469 &comment.Body, 470 &createdAt, 471 ) 472 if err != nil { 473 return nil, err ··· 475 476 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 477 comment.Created = t 478 } 479 480 atUri := comment.AtUri().String() ··· 522 p.created, 523 p.title, 524 p.state, 525 r.did, 526 r.name, 527 r.knot, 528 r.rkey, 529 - r.created 530 from 531 pulls p 532 join ··· 544 var pull models.Pull 545 var repo models.Repo 546 var pullCreatedAt, repoCreatedAt string 547 err := rows.Scan( 548 &pull.OwnerDid, 549 &pull.RepoAt, ··· 551 &pullCreatedAt, 552 &pull.Title, 553 &pull.State, 554 &repo.Did, 555 &repo.Name, 556 &repo.Knot, 557 &repo.Rkey, 558 &repoCreatedAt, 559 ) 560 if err != nil { 561 return nil, err 562 } 563 564 pullCreatedTime, err := time.Parse(time.RFC3339, pullCreatedAt) 565 if err != nil { 566 return nil, err ··· 572 return nil, err 573 } 574 repo.Created = repoCreatedTime 575 576 pull.Repo = &repo 577 ··· 586 } 587 588 func NewPullComment(tx *sql.Tx, comment *models.PullComment) (int64, error) { 589 - query := `insert into pull_comments (owner_did, repo_at, submission_id, comment_at, pull_id, body) values (?, ?, ?, ?, ?, ?)` 590 res, err := tx.Exec( 591 query, 592 comment.OwnerDid, ··· 595 comment.CommentAt, 596 comment.PullId, 597 comment.Body, 598 ) 599 if err != nil { 600 return 0, err ··· 614 615 func SetPullState(e Execer, repoAt syntax.ATURI, pullId int, pullState models.PullState) error { 616 _, err := e.Exec( 617 - `update pulls set state = ? where repo_at = ? and pull_id = ? and (state <> ? or state <> ?)`, 618 pullState, 619 repoAt, 620 pullId,
··· 18 ) 19 20 func NewPull(tx *sql.Tx, pull *models.Pull) error { 21 + var repoDid *string 22 + if pull.RepoDid != "" { 23 + repoDid = &pull.RepoDid 24 + } 25 + 26 _, err := tx.Exec(` 27 + insert into repo_pull_seqs (repo_at, repo_did, next_pull_id) 28 + values (?, ?, 1) 29 + on conflict(repo_at) do update set repo_did = coalesce(excluded.repo_did, repo_did) 30 + `, pull.RepoAt, repoDid) 31 if err != nil { 32 return err 33 } ··· 46 pull.PullId = nextId 47 pull.State = models.PullOpen 48 49 + var sourceBranch, sourceRepoAt, sourceRepoDid *string 50 if pull.PullSource != nil { 51 sourceBranch = &pull.PullSource.Branch 52 if pull.PullSource.RepoAt != nil { 53 x := pull.PullSource.RepoAt.String() 54 sourceRepoAt = &x 55 } 56 + if pull.PullSource.RepoDid != "" { 57 + sourceRepoDid = &pull.PullSource.RepoDid 58 + } 59 } 60 61 var stackId, changeId, parentChangeId *string ··· 72 result, err := tx.Exec( 73 ` 74 insert into pulls ( 75 + repo_at, owner_did, pull_id, title, target_branch, body, rkey, state, source_branch, source_repo_at, stack_id, change_id, parent_change_id, repo_did, source_repo_did 76 ) 77 + values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 78 pull.RepoAt, 79 pull.OwnerDid, 80 pull.PullId, ··· 88 stackId, 89 changeId, 90 parentChangeId, 91 + repoDid, 92 + sourceRepoDid, 93 ) 94 if err != nil { 95 return err ··· 170 source_repo_at, 171 stack_id, 172 change_id, 173 + parent_change_id, 174 + repo_did, 175 + source_repo_did 176 from 177 pulls 178 %s ··· 190 for rows.Next() { 191 var pull models.Pull 192 var createdAt string 193 + var sourceBranch, sourceRepoAt, stackId, changeId, parentChangeId, repoDid, sourceRepoDid sql.NullString 194 err := rows.Scan( 195 &pull.ID, 196 &pull.OwnerDid, ··· 207 &stackId, 208 &changeId, 209 &parentChangeId, 210 + &repoDid, 211 + &sourceRepoDid, 212 ) 213 if err != nil { 214 return nil, err ··· 231 } 232 pull.PullSource.RepoAt = &sourceRepoAtParsed 233 } 234 + if sourceRepoDid.Valid { 235 + pull.PullSource.RepoDid = sourceRepoDid.String 236 + } 237 } 238 239 if stackId.Valid { ··· 245 if parentChangeId.Valid { 246 pull.ParentChangeId = parentChangeId.String 247 } 248 + if repoDid.Valid { 249 + pull.RepoDid = repoDid.String 250 + } 251 252 pulls[pull.AtUri()] = &pull 253 } ··· 462 owner_did, 463 comment_at, 464 body, 465 + created, 466 + repo_did 467 from 468 pull_comments 469 %s ··· 481 for rows.Next() { 482 var comment models.PullComment 483 var createdAt string 484 + var commentRepoDid sql.NullString 485 err := rows.Scan( 486 &comment.ID, 487 &comment.PullId, ··· 491 &comment.CommentAt, 492 &comment.Body, 493 &createdAt, 494 + &commentRepoDid, 495 ) 496 if err != nil { 497 return nil, err ··· 499 500 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 501 comment.Created = t 502 + } 503 + if commentRepoDid.Valid { 504 + comment.RepoDid = commentRepoDid.String 505 } 506 507 atUri := comment.AtUri().String() ··· 549 p.created, 550 p.title, 551 p.state, 552 + p.repo_did, 553 r.did, 554 r.name, 555 r.knot, 556 r.rkey, 557 + r.created, 558 + r.repo_did 559 from 560 pulls p 561 join ··· 573 var pull models.Pull 574 var repo models.Repo 575 var pullCreatedAt, repoCreatedAt string 576 + var pullRepoDid, repoRepoDid sql.NullString 577 err := rows.Scan( 578 &pull.OwnerDid, 579 &pull.RepoAt, ··· 581 &pullCreatedAt, 582 &pull.Title, 583 &pull.State, 584 + &pullRepoDid, 585 &repo.Did, 586 &repo.Name, 587 &repo.Knot, 588 &repo.Rkey, 589 &repoCreatedAt, 590 + &repoRepoDid, 591 ) 592 if err != nil { 593 return nil, err 594 } 595 596 + if pullRepoDid.Valid { 597 + pull.RepoDid = pullRepoDid.String 598 + } 599 + 600 pullCreatedTime, err := time.Parse(time.RFC3339, pullCreatedAt) 601 if err != nil { 602 return nil, err ··· 608 return nil, err 609 } 610 repo.Created = repoCreatedTime 611 + if repoRepoDid.Valid { 612 + repo.RepoDid = repoRepoDid.String 613 + } 614 615 pull.Repo = &repo 616 ··· 625 } 626 627 func NewPullComment(tx *sql.Tx, comment *models.PullComment) (int64, error) { 628 + var repoDid *string 629 + if comment.RepoDid != "" { 630 + repoDid = &comment.RepoDid 631 + } 632 + 633 + query := `insert into pull_comments (owner_did, repo_at, submission_id, comment_at, pull_id, body, repo_did) values (?, ?, ?, ?, ?, ?, ?)` 634 res, err := tx.Exec( 635 query, 636 comment.OwnerDid, ··· 639 comment.CommentAt, 640 comment.PullId, 641 comment.Body, 642 + repoDid, 643 ) 644 if err != nil { 645 return 0, err ··· 659 660 func SetPullState(e Execer, repoAt syntax.ATURI, pullId int, pullState models.PullState) error { 661 _, err := e.Exec( 662 + `update pulls set state = ? where repo_at = ? and pull_id = ? and (state <> ? and state <> ?)`, 663 pullState, 664 repoAt, 665 pullId,
+36 -12
appview/db/reference.go
··· 60 on r.did = inp.owner_did 61 and r.name = inp.name 62 join issues i 63 - on i.repo_at = r.at_uri 64 and i.issue_id = inp.issue_id 65 left join issue_comments c 66 on inp.comment_id is not null ··· 131 on r.did = inp.owner_did 132 and r.name = inp.name 133 join pulls p 134 - on p.repo_at = r.at_uri 135 and p.pull_id = inp.pull_id 136 left join pull_comments c 137 on inp.comment_id is not null 138 - and c.repo_at = r.at_uri and c.pull_id = p.pull_id 139 and c.id = inp.comment_id 140 `, 141 strings.Join(vals, ","), ··· 316 } 317 rows, err := e.Query( 318 fmt.Sprintf( 319 - `select r.did, r.name, i.issue_id, i.title, i.open 320 from issues i 321 join repos r 322 - on r.at_uri = i.repo_at 323 where (i.did, i.rkey) in (%s)`, 324 strings.Join(vals, ","), 325 ), ··· 351 filter := orm.FilterIn("c.at_uri", aturis) 352 rows, err := e.Query( 353 fmt.Sprintf( 354 - `select r.did, r.name, i.issue_id, c.id, i.title, i.open 355 from issue_comments c 356 join issues i 357 on i.at_uri = c.issue_at 358 join repos r 359 - on r.at_uri = i.repo_at 360 where %s`, 361 filter.Condition(), 362 ), ··· 396 } 397 rows, err := e.Query( 398 fmt.Sprintf( 399 - `select r.did, r.name, p.pull_id, p.title, p.state 400 from pulls p 401 join repos r 402 - on r.at_uri = p.repo_at 403 where (p.owner_did, p.rkey) in (%s)`, 404 strings.Join(vals, ","), 405 ), ··· 431 filter := orm.FilterIn("c.comment_at", aturis) 432 rows, err := e.Query( 433 fmt.Sprintf( 434 - `select r.did, r.name, p.pull_id, c.id, p.title, p.state 435 from repos r 436 join pulls p 437 - on r.at_uri = p.repo_at 438 join pull_comments c 439 - on r.at_uri = c.repo_at and p.pull_id = c.pull_id 440 where %s`, 441 filter.Condition(), 442 ),
··· 60 on r.did = inp.owner_did 61 and r.name = inp.name 62 join issues i 63 + on coalesce( 64 + nullif(i.repo_did, '') = nullif(r.repo_did, ''), 65 + i.repo_at = r.at_uri 66 + ) 67 and i.issue_id = inp.issue_id 68 left join issue_comments c 69 on inp.comment_id is not null ··· 134 on r.did = inp.owner_did 135 and r.name = inp.name 136 join pulls p 137 + on coalesce( 138 + nullif(p.repo_did, '') = nullif(r.repo_did, ''), 139 + p.repo_at = r.at_uri 140 + ) 141 and p.pull_id = inp.pull_id 142 left join pull_comments c 143 on inp.comment_id is not null 144 + and coalesce( 145 + nullif(c.repo_did, '') = nullif(r.repo_did, ''), 146 + c.repo_at = r.at_uri 147 + ) and c.pull_id = p.pull_id 148 and c.id = inp.comment_id 149 `, 150 strings.Join(vals, ","), ··· 325 } 326 rows, err := e.Query( 327 fmt.Sprintf( 328 + `select distinct r.did, r.name, i.issue_id, i.title, i.open 329 from issues i 330 join repos r 331 + on coalesce( 332 + nullif(i.repo_did, '') = nullif(r.repo_did, ''), 333 + i.repo_at = r.at_uri 334 + ) 335 where (i.did, i.rkey) in (%s)`, 336 strings.Join(vals, ","), 337 ), ··· 363 filter := orm.FilterIn("c.at_uri", aturis) 364 rows, err := e.Query( 365 fmt.Sprintf( 366 + `select distinct r.did, r.name, i.issue_id, c.id, i.title, i.open 367 from issue_comments c 368 join issues i 369 on i.at_uri = c.issue_at 370 join repos r 371 + on coalesce( 372 + nullif(i.repo_did, '') = nullif(r.repo_did, ''), 373 + i.repo_at = r.at_uri 374 + ) 375 where %s`, 376 filter.Condition(), 377 ), ··· 411 } 412 rows, err := e.Query( 413 fmt.Sprintf( 414 + `select distinct r.did, r.name, p.pull_id, p.title, p.state 415 from pulls p 416 join repos r 417 + on coalesce( 418 + nullif(p.repo_did, '') = nullif(r.repo_did, ''), 419 + p.repo_at = r.at_uri 420 + ) 421 where (p.owner_did, p.rkey) in (%s)`, 422 strings.Join(vals, ","), 423 ), ··· 449 filter := orm.FilterIn("c.comment_at", aturis) 450 rows, err := e.Query( 451 fmt.Sprintf( 452 + `select distinct r.did, r.name, p.pull_id, c.id, p.title, p.state 453 from repos r 454 join pulls p 455 + on coalesce( 456 + nullif(p.repo_did, '') = nullif(r.repo_did, ''), 457 + p.repo_at = r.at_uri 458 + ) 459 join pull_comments c 460 + on coalesce( 461 + nullif(c.repo_did, '') = nullif(r.repo_did, ''), 462 + c.repo_at = r.at_uri 463 + ) and p.pull_id = c.pull_id 464 where %s`, 465 filter.Condition(), 466 ),
+107 -26
appview/db/repos.go
··· 46 website, 47 topics, 48 source, 49 - spindle 50 from 51 repos r 52 %s ··· 64 for rows.Next() { 65 var repo models.Repo 66 var createdAt string 67 - var description, website, topicStr, source, spindle sql.NullString 68 69 err := rows.Scan( 70 &repo.Id, ··· 78 &topicStr, 79 &source, 80 &spindle, 81 ) 82 if err != nil { 83 return nil, fmt.Errorf("failed to execute repo query: %w ", err) ··· 100 } 101 if spindle.Valid { 102 repo.Spindle = spindle.String 103 } 104 105 repo.RepoStats = &models.RepoStats{} ··· 184 return nil, fmt.Errorf("failed to execute lang query: %w ", err) 185 } 186 187 starCountQuery := fmt.Sprintf( 188 - `select 189 - subject_at, count(1) 190 from stars 191 - where subject_at in (%s) 192 - group by subject_at`, 193 - inClause, 194 ) 195 - rows, err = e.Query(starCountQuery, args...) 196 if err != nil { 197 return nil, fmt.Errorf("failed to execute star-count query: %w ", err) 198 } 199 defer rows.Close() 200 201 for rows.Next() { 202 - var repoat string 203 var count int 204 - if err := rows.Scan(&repoat, &count); err != nil { 205 log.Println("err", "err", err) 206 continue 207 } 208 - if r, ok := repoMap[syntax.ATURI(repoat)]; ok { 209 r.RepoStats.StarCount = count 210 } 211 } 212 if err = rows.Err(); err != nil { ··· 352 var nullableDescription sql.NullString 353 var nullableWebsite sql.NullString 354 var nullableTopicStr sql.NullString 355 356 - row := e.QueryRow(`select id, did, name, knot, created, rkey, description, website, topics from repos where at_uri = ?`, atUri) 357 358 var createdAt string 359 - if err := row.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.Rkey, &nullableDescription, &nullableWebsite, &nullableTopicStr); err != nil { 360 return nil, err 361 } 362 createdAtTime, _ := time.Parse(time.RFC3339, createdAt) ··· 371 if nullableTopicStr.Valid { 372 repo.Topics = strings.Fields(nullableTopicStr.String) 373 } 374 375 return &repo, nil 376 } 377 378 func PutRepo(tx *sql.Tx, repo models.Repo) error { 379 _, err := tx.Exec( 380 `update repos 381 - set knot = ?, description = ?, website = ?, topics = ? 382 where did = ? and rkey = ? 383 `, 384 - repo.Knot, repo.Description, repo.Website, repo.TopicStr(), repo.Did, repo.Rkey, 385 ) 386 return err 387 } 388 389 func AddRepo(tx *sql.Tx, repo *models.Repo) error { 390 _, err := tx.Exec( 391 `insert into repos 392 - (did, name, knot, rkey, at_uri, description, website, topics, source) 393 - values (?, ?, ?, ?, ?, ?, ?, ?, ?)`, 394 - repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.RepoAt().String(), repo.Description, repo.Website, repo.TopicStr(), repo.Source, 395 ) 396 if err != nil { 397 return fmt.Errorf("failed to insert repo: %w", err) ··· 401 if err := SubscribeLabel(tx, &models.RepoLabel{ 402 RepoAt: repo.RepoAt(), 403 LabelAt: syntax.ATURI(dl), 404 }); err != nil { 405 return fmt.Errorf("failed to subscribe to label: %w", err) 406 } ··· 431 if err != nil { 432 return nil, err 433 } 434 return GetRepoByAtUri(e, source) 435 } 436 ··· 438 var repos []models.Repo 439 440 rows, err := e.Query( 441 - `select distinct r.id, r.did, r.name, r.knot, r.rkey, r.description, r.website, r.created, r.source 442 from repos r 443 left join collaborators c on r.at_uri = c.repo_at 444 where (r.did = ? or c.subject_did = ?) ··· 458 var nullableDescription sql.NullString 459 var nullableWebsite sql.NullString 460 var nullableSource sql.NullString 461 462 - err := rows.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &nullableWebsite, &createdAt, &nullableSource) 463 if err != nil { 464 return nil, err 465 } ··· 467 if nullableDescription.Valid { 468 repo.Description = nullableDescription.String 469 } 470 471 if nullableSource.Valid { 472 repo.Source = nullableSource.String 473 } 474 475 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 476 if err != nil { ··· 496 var nullableWebsite sql.NullString 497 var nullableTopicStr sql.NullString 498 var nullableSource sql.NullString 499 500 row := e.QueryRow( 501 - `select id, did, name, knot, rkey, description, website, topics, created, source 502 from repos 503 where did = ? and name = ? and source is not null and source != ''`, 504 did, name, 505 ) 506 507 - err := row.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &nullableWebsite, &nullableTopicStr, &createdAt, &nullableSource) 508 if err != nil { 509 return nil, err 510 } ··· 524 if nullableSource.Valid { 525 repo.Source = nullableSource.String 526 } 527 528 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 529 if err != nil { ··· 535 return &repo, nil 536 } 537 538 func UpdateDescription(e Execer, repoAt, newDescription string) error { 539 _, err := e.Exec( 540 `update repos set description = ? where at_uri = ?`, newDescription, repoAt) ··· 548 } 549 550 func SubscribeLabel(e Execer, rl *models.RepoLabel) error { 551 - query := `insert or ignore into repo_labels (repo_at, label_at) values (?, ?)` 552 553 - _, err := e.Exec(query, rl.RepoAt.String(), rl.LabelAt.String()) 554 return err 555 } 556 ··· 585 whereClause = " where " + strings.Join(conditions, " and ") 586 } 587 588 - query := fmt.Sprintf(`select id, repo_at, label_at from repo_labels %s`, whereClause) 589 590 rows, err := e.Query(query, args...) 591 if err != nil { ··· 596 var labels []models.RepoLabel 597 for rows.Next() { 598 var label models.RepoLabel 599 600 - err := rows.Scan(&label.Id, &label.RepoAt, &label.LabelAt) 601 if err != nil { 602 return nil, err 603 } 604 605 labels = append(labels, label)
··· 46 website, 47 topics, 48 source, 49 + spindle, 50 + repo_did 51 from 52 repos r 53 %s ··· 65 for rows.Next() { 66 var repo models.Repo 67 var createdAt string 68 + var description, website, topicStr, source, spindle, repoDid sql.NullString 69 70 err := rows.Scan( 71 &repo.Id, ··· 79 &topicStr, 80 &source, 81 &spindle, 82 + &repoDid, 83 ) 84 if err != nil { 85 return nil, fmt.Errorf("failed to execute repo query: %w ", err) ··· 102 } 103 if spindle.Valid { 104 repo.Spindle = spindle.String 105 + } 106 + if repoDid.Valid { 107 + repo.RepoDid = repoDid.String 108 } 109 110 repo.RepoStats = &models.RepoStats{} ··· 189 return nil, fmt.Errorf("failed to execute lang query: %w ", err) 190 } 191 192 + var repoDids []any 193 + repoDidToAt := make(map[string]syntax.ATURI) 194 + for atUri, r := range repoMap { 195 + if r.RepoDid != "" { 196 + repoDids = append(repoDids, r.RepoDid) 197 + repoDidToAt[r.RepoDid] = atUri 198 + } 199 + } 200 + 201 + didInClause := "''" 202 + if len(repoDids) > 0 { 203 + didInClause = strings.TrimSuffix(strings.Repeat("?, ", len(repoDids)), ", ") 204 + } 205 starCountQuery := fmt.Sprintf( 206 + `select coalesce(subject_did, subject_at) as key, count(1) 207 from stars 208 + where subject_at in (%s) or subject_did in (%s) 209 + group by key`, 210 + inClause, didInClause, 211 ) 212 + starArgs := append(append([]any{}, args...), repoDids...) 213 + rows, err = e.Query(starCountQuery, starArgs...) 214 if err != nil { 215 return nil, fmt.Errorf("failed to execute star-count query: %w ", err) 216 } 217 defer rows.Close() 218 219 for rows.Next() { 220 + var key string 221 var count int 222 + if err := rows.Scan(&key, &count); err != nil { 223 log.Println("err", "err", err) 224 continue 225 } 226 + if r, ok := repoMap[syntax.ATURI(key)]; ok { 227 r.RepoStats.StarCount = count 228 + } else if atUri, ok := repoDidToAt[key]; ok { 229 + if r, ok := repoMap[atUri]; ok { 230 + r.RepoStats.StarCount = count 231 + } 232 } 233 } 234 if err = rows.Err(); err != nil { ··· 374 var nullableDescription sql.NullString 375 var nullableWebsite sql.NullString 376 var nullableTopicStr sql.NullString 377 + var nullableRepoDid sql.NullString 378 + var nullableSource sql.NullString 379 + var nullableSpindle sql.NullString 380 381 + row := e.QueryRow(`select id, did, name, knot, created, rkey, description, website, topics, source, spindle, repo_did from repos where at_uri = ?`, atUri) 382 383 var createdAt string 384 + if err := row.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &createdAt, &repo.Rkey, &nullableDescription, &nullableWebsite, &nullableTopicStr, &nullableSource, &nullableSpindle, &nullableRepoDid); err != nil { 385 return nil, err 386 } 387 createdAtTime, _ := time.Parse(time.RFC3339, createdAt) ··· 396 if nullableTopicStr.Valid { 397 repo.Topics = strings.Fields(nullableTopicStr.String) 398 } 399 + if nullableSource.Valid { 400 + repo.Source = nullableSource.String 401 + } 402 + if nullableSpindle.Valid { 403 + repo.Spindle = nullableSpindle.String 404 + } 405 + if nullableRepoDid.Valid { 406 + repo.RepoDid = nullableRepoDid.String 407 + } 408 409 return &repo, nil 410 } 411 412 func PutRepo(tx *sql.Tx, repo models.Repo) error { 413 + var repoDid *string 414 + if repo.RepoDid != "" { 415 + repoDid = &repo.RepoDid 416 + } 417 _, err := tx.Exec( 418 `update repos 419 + set knot = ?, description = ?, website = ?, topics = ?, repo_did = coalesce(?, repo_did) 420 where did = ? and rkey = ? 421 `, 422 + repo.Knot, repo.Description, repo.Website, repo.TopicStr(), repoDid, repo.Did, repo.Rkey, 423 ) 424 return err 425 } 426 427 func AddRepo(tx *sql.Tx, repo *models.Repo) error { 428 + var repoDid *string 429 + if repo.RepoDid != "" { 430 + repoDid = &repo.RepoDid 431 + } 432 _, err := tx.Exec( 433 `insert into repos 434 + (did, name, knot, rkey, at_uri, description, website, topics, source, repo_did) 435 + values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 436 + repo.Did, repo.Name, repo.Knot, repo.Rkey, repo.RepoAt().String(), repo.Description, repo.Website, repo.TopicStr(), repo.Source, repoDid, 437 ) 438 if err != nil { 439 return fmt.Errorf("failed to insert repo: %w", err) ··· 443 if err := SubscribeLabel(tx, &models.RepoLabel{ 444 RepoAt: repo.RepoAt(), 445 LabelAt: syntax.ATURI(dl), 446 + RepoDid: repo.RepoDid, 447 }); err != nil { 448 return fmt.Errorf("failed to subscribe to label: %w", err) 449 } ··· 474 if err != nil { 475 return nil, err 476 } 477 + if strings.HasPrefix(source, "did:") { 478 + return GetRepoByDid(e, source) 479 + } 480 return GetRepoByAtUri(e, source) 481 } 482 ··· 484 var repos []models.Repo 485 486 rows, err := e.Query( 487 + `select distinct r.id, r.did, r.name, r.knot, r.rkey, r.description, r.website, r.created, r.source, r.repo_did 488 from repos r 489 left join collaborators c on r.at_uri = c.repo_at 490 where (r.did = ? or c.subject_did = ?) ··· 504 var nullableDescription sql.NullString 505 var nullableWebsite sql.NullString 506 var nullableSource sql.NullString 507 + var nullableRepoDid sql.NullString 508 509 + err := rows.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &nullableWebsite, &createdAt, &nullableSource, &nullableRepoDid) 510 if err != nil { 511 return nil, err 512 } ··· 514 if nullableDescription.Valid { 515 repo.Description = nullableDescription.String 516 } 517 + if nullableWebsite.Valid { 518 + repo.Website = nullableWebsite.String 519 + } 520 521 if nullableSource.Valid { 522 repo.Source = nullableSource.String 523 } 524 + if nullableRepoDid.Valid { 525 + repo.RepoDid = nullableRepoDid.String 526 + } 527 528 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 529 if err != nil { ··· 549 var nullableWebsite sql.NullString 550 var nullableTopicStr sql.NullString 551 var nullableSource sql.NullString 552 + var nullableRepoDid sql.NullString 553 554 row := e.QueryRow( 555 + `select id, did, name, knot, rkey, description, website, topics, created, source, repo_did 556 from repos 557 where did = ? and name = ? and source is not null and source != ''`, 558 did, name, 559 ) 560 561 + err := row.Scan(&repo.Id, &repo.Did, &repo.Name, &repo.Knot, &repo.Rkey, &nullableDescription, &nullableWebsite, &nullableTopicStr, &createdAt, &nullableSource, &nullableRepoDid) 562 if err != nil { 563 return nil, err 564 } ··· 578 if nullableSource.Valid { 579 repo.Source = nullableSource.String 580 } 581 + if nullableRepoDid.Valid { 582 + repo.RepoDid = nullableRepoDid.String 583 + } 584 585 createdAtTime, err := time.Parse(time.RFC3339, createdAt) 586 if err != nil { ··· 592 return &repo, nil 593 } 594 595 + func GetRepoByDid(e Execer, repoDid string) (*models.Repo, error) { 596 + return GetRepo(e, orm.FilterEq("repo_did", repoDid)) 597 + } 598 + 599 + func EnqueuePdsRewrite(e Execer, userDid, repoDid, recordNsid, recordRkey, oldRepoAt string) error { 600 + _, err := e.Exec( 601 + `INSERT OR IGNORE INTO pds_rewrite_status 602 + (user_did, repo_did, record_nsid, record_rkey, old_repo_at, status) 603 + VALUES (?, ?, ?, ?, ?, 'pending')`, 604 + userDid, repoDid, recordNsid, recordRkey, oldRepoAt, 605 + ) 606 + return err 607 + } 608 + 609 func UpdateDescription(e Execer, repoAt, newDescription string) error { 610 _, err := e.Exec( 611 `update repos set description = ? where at_uri = ?`, newDescription, repoAt) ··· 619 } 620 621 func SubscribeLabel(e Execer, rl *models.RepoLabel) error { 622 + var repoDid *string 623 + if rl.RepoDid != "" { 624 + repoDid = &rl.RepoDid 625 + } 626 + query := `insert into repo_labels (repo_at, label_at, repo_did) 627 + values (?, ?, ?) 628 + on conflict(repo_at, label_at) do update set repo_did = coalesce(excluded.repo_did, repo_did)` 629 630 + _, err := e.Exec(query, rl.RepoAt.String(), rl.LabelAt.String(), repoDid) 631 return err 632 } 633 ··· 662 whereClause = " where " + strings.Join(conditions, " and ") 663 } 664 665 + query := fmt.Sprintf(`select id, repo_at, label_at, repo_did from repo_labels %s`, whereClause) 666 667 rows, err := e.Query(query, args...) 668 if err != nil { ··· 673 var labels []models.RepoLabel 674 for rows.Next() { 675 var label models.RepoLabel 676 + var labelRepoDid sql.NullString 677 678 + err := rows.Scan(&label.Id, &label.RepoAt, &label.LabelAt, &labelRepoDid) 679 if err != nil { 680 return nil, err 681 + } 682 + if labelRepoDid.Valid { 683 + label.RepoDid = labelRepoDid.String 684 } 685 686 labels = append(labels, label)
+29 -5
appview/db/star.go
··· 15 ) 16 17 func AddStar(e Execer, star *models.Star) error { 18 - query := `insert or ignore into stars (did, subject_at, rkey) values (?, ?, ?)` 19 _, err := e.Exec( 20 query, 21 star.Did, 22 star.RepoAt.String(), 23 star.Rkey, 24 ) 25 return err 26 } ··· 28 // Get a star record 29 func GetStar(e Execer, did string, subjectAt syntax.ATURI) (*models.Star, error) { 30 query := ` 31 - select did, subject_at, created, rkey 32 from stars 33 where did = ? and subject_at = ?` 34 row := e.QueryRow(query, did, subjectAt) 35 36 var star models.Star 37 var created string 38 - err := row.Scan(&star.Did, &star.RepoAt, &created, &star.Rkey) 39 if err != nil { 40 return nil, err 41 } 42 43 createdAtTime, err := time.Parse(time.RFC3339, created) ··· 73 return stars, nil 74 } 75 76 // getStarStatuses returns a map of repo URIs to star status for a given user 77 // This is an internal helper function to avoid N+1 queries 78 func getStarStatuses(e Execer, userDid string, repoAts []syntax.ATURI) (map[string]bool, error) { ··· 153 } 154 155 repoQuery := fmt.Sprintf( 156 - `select did, subject_at, created, rkey 157 from stars 158 %s 159 order by created desc ··· 171 for rows.Next() { 172 var star models.Star 173 var created string 174 - err := rows.Scan(&star.Did, &star.RepoAt, &created, &star.Rkey) 175 if err != nil { 176 return nil, err 177 } 178 179 star.Created = time.Now()
··· 15 ) 16 17 func AddStar(e Execer, star *models.Star) error { 18 + query := `insert or ignore into stars (did, subject_at, rkey, subject_did) values (?, ?, ?, ?)` 19 + var subjectDid *string 20 + if star.SubjectDid != "" { 21 + subjectDid = &star.SubjectDid 22 + } 23 _, err := e.Exec( 24 query, 25 star.Did, 26 star.RepoAt.String(), 27 star.Rkey, 28 + subjectDid, 29 ) 30 return err 31 } ··· 33 // Get a star record 34 func GetStar(e Execer, did string, subjectAt syntax.ATURI) (*models.Star, error) { 35 query := ` 36 + select did, subject_at, created, rkey, subject_did 37 from stars 38 where did = ? and subject_at = ?` 39 row := e.QueryRow(query, did, subjectAt) 40 41 var star models.Star 42 var created string 43 + var nullableSubjectDid sql.NullString 44 + err := row.Scan(&star.Did, &star.RepoAt, &created, &star.Rkey, &nullableSubjectDid) 45 if err != nil { 46 return nil, err 47 + } 48 + if nullableSubjectDid.Valid { 49 + star.SubjectDid = nullableSubjectDid.String 50 } 51 52 createdAtTime, err := time.Parse(time.RFC3339, created) ··· 82 return stars, nil 83 } 84 85 + func GetStarCountByRepoDid(e Execer, repoDid string, repoAt syntax.ATURI) (int, error) { 86 + stars := 0 87 + err := e.QueryRow( 88 + `select count(did) from stars where subject_did = ? or subject_at = ?`, 89 + repoDid, repoAt.String()).Scan(&stars) 90 + if err != nil { 91 + return 0, err 92 + } 93 + return stars, nil 94 + } 95 + 96 // getStarStatuses returns a map of repo URIs to star status for a given user 97 // This is an internal helper function to avoid N+1 queries 98 func getStarStatuses(e Execer, userDid string, repoAts []syntax.ATURI) (map[string]bool, error) { ··· 173 } 174 175 repoQuery := fmt.Sprintf( 176 + `select did, subject_at, created, rkey, subject_did 177 from stars 178 %s 179 order by created desc ··· 191 for rows.Next() { 192 var star models.Star 193 var created string 194 + var nullableSubjectDid sql.NullString 195 + err := rows.Scan(&star.Did, &star.RepoAt, &created, &star.Rkey, &nullableSubjectDid) 196 if err != nil { 197 return nil, err 198 + } 199 + if nullableSubjectDid.Valid { 200 + star.SubjectDid = nullableSubjectDid.String 201 } 202 203 star.Created = time.Now()
+15 -5
appview/db/webhooks.go
··· 34 active, 35 events, 36 created_at, 37 - updated_at 38 from webhooks 39 %s 40 order by created_at desc ··· 50 for rows.Next() { 51 var wh models.Webhook 52 var createdAt, updatedAt, eventsStr string 53 - var secret sql.NullString 54 var active int 55 56 err := rows.Scan( ··· 62 &eventsStr, 63 &createdAt, 64 &updatedAt, 65 ) 66 if err != nil { 67 return nil, fmt.Errorf("failed to scan webhook: %w", err) ··· 80 } 81 if t, err := time.Parse(time.RFC3339, updatedAt); err == nil { 82 wh.UpdatedAt = t 83 } 84 85 webhooks = append(webhooks, wh) ··· 118 active = 1 119 } 120 121 result, err := e.Exec(` 122 - insert into webhooks (repo_at, url, secret, active, events) 123 - values (?, ?, ?, ?, ?) 124 - `, webhook.RepoAt.String(), webhook.Url, webhook.Secret, active, eventsStr) 125 126 if err != nil { 127 return fmt.Errorf("failed to insert webhook: %w", err)
··· 34 active, 35 events, 36 created_at, 37 + updated_at, 38 + repo_did 39 from webhooks 40 %s 41 order by created_at desc ··· 51 for rows.Next() { 52 var wh models.Webhook 53 var createdAt, updatedAt, eventsStr string 54 + var secret, whRepoDid sql.NullString 55 var active int 56 57 err := rows.Scan( ··· 63 &eventsStr, 64 &createdAt, 65 &updatedAt, 66 + &whRepoDid, 67 ) 68 if err != nil { 69 return nil, fmt.Errorf("failed to scan webhook: %w", err) ··· 82 } 83 if t, err := time.Parse(time.RFC3339, updatedAt); err == nil { 84 wh.UpdatedAt = t 85 + } 86 + if whRepoDid.Valid { 87 + wh.RepoDid = whRepoDid.String 88 } 89 90 webhooks = append(webhooks, wh) ··· 123 active = 1 124 } 125 126 + var repoDid *string 127 + if webhook.RepoDid != "" { 128 + repoDid = &webhook.RepoDid 129 + } 130 + 131 result, err := e.Exec(` 132 + insert into webhooks (repo_at, url, secret, active, events, repo_did) 133 + values (?, ?, ?, ?, ?, ?) 134 + `, webhook.RepoAt.String(), webhook.Url, webhook.Secret, active, eventsStr, repoDid) 135 136 if err != nil { 137 return fmt.Errorf("failed to insert webhook: %w", err)