package dolt import ( "context" "fmt" "strings" "github.com/steveyegge/beads/internal/types" ) // AddLabel adds a label to an issue func (s *DoltStore) AddLabel(ctx context.Context, issueID, label, actor string) error { _, err := s.db.ExecContext(ctx, ` INSERT IGNORE INTO labels (issue_id, label) VALUES (?, ?) `, issueID, label) if err != nil { return fmt.Errorf("failed to add label: %w", err) } return nil } // RemoveLabel removes a label from an issue func (s *DoltStore) RemoveLabel(ctx context.Context, issueID, label, actor string) error { _, err := s.db.ExecContext(ctx, ` DELETE FROM labels WHERE issue_id = ? AND label = ? `, issueID, label) if err != nil { return fmt.Errorf("failed to remove label: %w", err) } return nil } // GetLabels retrieves all labels for an issue func (s *DoltStore) GetLabels(ctx context.Context, issueID string) ([]string, error) { rows, err := s.db.QueryContext(ctx, ` SELECT label FROM labels WHERE issue_id = ? ORDER BY label `, issueID) if err != nil { return nil, fmt.Errorf("failed to get labels: %w", err) } defer rows.Close() var labels []string for rows.Next() { var label string if err := rows.Scan(&label); err != nil { return nil, fmt.Errorf("failed to scan label: %w", err) } labels = append(labels, label) } return labels, rows.Err() } // GetLabelsForIssues retrieves labels for multiple issues func (s *DoltStore) GetLabelsForIssues(ctx context.Context, issueIDs []string) (map[string][]string, error) { if len(issueIDs) == 0 { return make(map[string][]string), nil } placeholders := make([]string, len(issueIDs)) args := make([]interface{}, len(issueIDs)) for i, id := range issueIDs { placeholders[i] = "?" args[i] = id } query := fmt.Sprintf(` SELECT issue_id, label FROM labels WHERE issue_id IN (%s) ORDER BY issue_id, label `, strings.Join(placeholders, ",")) rows, err := s.db.QueryContext(ctx, query, args...) if err != nil { return nil, fmt.Errorf("failed to get labels for issues: %w", err) } defer rows.Close() result := make(map[string][]string) for rows.Next() { var issueID, label string if err := rows.Scan(&issueID, &label); err != nil { return nil, fmt.Errorf("failed to scan label: %w", err) } result[issueID] = append(result[issueID], label) } return result, rows.Err() } // GetIssuesByLabel retrieves all issues with a specific label func (s *DoltStore) GetIssuesByLabel(ctx context.Context, label string) ([]*types.Issue, error) { rows, err := s.db.QueryContext(ctx, ` SELECT i.id FROM issues i JOIN labels l ON i.id = l.issue_id WHERE l.label = ? ORDER BY i.priority ASC, i.created_at DESC `, label) if err != nil { return nil, fmt.Errorf("failed to get issues by label: %w", err) } defer rows.Close() var issues []*types.Issue for rows.Next() { var id string if err := rows.Scan(&id); err != nil { return nil, fmt.Errorf("failed to scan issue id: %w", err) } issue, err := s.GetIssue(ctx, id) if err != nil { return nil, err } if issue != nil { issues = append(issues, issue) } } return issues, rows.Err() }