MCPcopy Create free account
hub / github.com/PerpetualSoftware/pad / ListWorkspaceGraphLinks

Method ListWorkspaceGraphLinks

internal/store/graph.go:57–125  ·  view source on GitHub ↗

ListWorkspaceGraphLinks returns every edge for the workspace graph view: all item_links rows (parent / blocks / implements / related) plus resolved same-workspace wiki-links from the item_wiki_links reverse index (PLAN-1593). Both queries exclude edges whose source or target item is soft-deleted, m

(workspaceID string)

Source from the content-addressed store, hash-verified

55// structure). Unresolved rows (target_item_id IS NULL) and
56// cross-workspace rows are excluded: the graph renders one workspace.
57func (s *Store) ListWorkspaceGraphLinks(workspaceID string) ([]GraphLink, error) {
58 links := []GraphLink{}
59
60 rows, err := s.db.Query(s.q(`
61 SELECT il.source_id, il.target_id, il.link_type
62 FROM item_links il
63 JOIN items src ON src.id = il.source_id AND src.deleted_at IS NULL
64 JOIN items tgt ON tgt.id = il.target_id AND tgt.deleted_at IS NULL
65 WHERE il.workspace_id = ?
66 `), workspaceID)
67 if err != nil {
68 return nil, fmt.Errorf("list graph item links: %w", err)
69 }
70 defer rows.Close()
71 for rows.Next() {
72 var l GraphLink
73 if err := rows.Scan(&l.SourceID, &l.TargetID, &l.Type); err != nil {
74 return nil, fmt.Errorf("scan graph item link: %w", err)
75 }
76 l.Type = graphEdgeType(l.Type)
77 links = append(links, l)
78 }
79 if err := rows.Err(); err != nil {
80 return nil, err
81 }
82
83 // Wiki-link edges. Scoped by the SOURCE item's workspace —
84 // item_wiki_links has no workspace_id column of its own, and
85 // target_workspace_id is only set on cross-workspace rows (which
86 // are excluded here anyway).
87 wikiRows, err := s.db.Query(s.q(`
88 SELECT DISTINCT wl.source_item_id, wl.target_item_id
89 FROM item_wiki_links wl
90 JOIN items src ON src.id = wl.source_item_id AND src.deleted_at IS NULL
91 JOIN items tgt ON tgt.id = wl.target_item_id AND tgt.deleted_at IS NULL
92 WHERE src.workspace_id = ?
93 AND wl.target_item_id IS NOT NULL
94 AND wl.target_workspace_id IS NULL
95 AND wl.source_item_id != wl.target_item_id
96 `), workspaceID)
97 if err != nil {
98 return nil, fmt.Errorf("list graph wiki links: %w", err)
99 }
100 defer wikiRows.Close()
101 for wikiRows.Next() {
102 l := GraphLink{Type: "wiki-link"}
103 if err := wikiRows.Scan(&l.SourceID, &l.TargetID); err != nil {
104 return nil, fmt.Errorf("scan graph wiki link: %w", err)
105 }
106 links = append(links, l)
107 }
108 if err := wikiRows.Err(); err != nil {
109 return nil, err
110 }
111
112 // Dedupe (source, target, type) — a stored wiki_link item_links row
113 // and a parsed [[...]] mention of the same pair both normalize to
114 // 'wiki-link' and would otherwise emit twice.

Callers 1

Calls 5

qMethod · 0.95
graphEdgeTypeFunction · 0.85
QueryMethod · 0.80
ScanMethod · 0.80
CloseMethod · 0.65

Tested by

no test coverage detected