package dolt import ( "context" "fmt" "time" "github.com/steveyegge/beads/internal/types" ) // UpdateIssueID updates an issue ID and all its references func (s *DoltStore) UpdateIssueID(ctx context.Context, oldID, newID string, issue *types.Issue, actor string) error { tx, err := s.db.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } defer func() { _ = tx.Rollback() }() // Update the issue itself result, err := tx.ExecContext(ctx, ` UPDATE issues SET id = ?, title = ?, description = ?, design = ?, acceptance_criteria = ?, notes = ?, updated_at = ? WHERE id = ? `, newID, issue.Title, issue.Description, issue.Design, issue.AcceptanceCriteria, issue.Notes, time.Now().UTC(), oldID) if err != nil { return fmt.Errorf("failed to update issue ID: %w", err) } rows, err := result.RowsAffected() if err != nil { return fmt.Errorf("failed to get rows affected: %w", err) } if rows == 0 { return fmt.Errorf("issue not found: %s", oldID) } // Update references in dependencies _, err = tx.ExecContext(ctx, `UPDATE dependencies SET issue_id = ? WHERE issue_id = ?`, newID, oldID) if err != nil { return fmt.Errorf("failed to update issue_id in dependencies: %w", err) } _, err = tx.ExecContext(ctx, `UPDATE dependencies SET depends_on_id = ? WHERE depends_on_id = ?`, newID, oldID) if err != nil { return fmt.Errorf("failed to update depends_on_id in dependencies: %w", err) } // Update references in events _, err = tx.ExecContext(ctx, `UPDATE events SET issue_id = ? WHERE issue_id = ?`, newID, oldID) if err != nil { return fmt.Errorf("failed to update events: %w", err) } // Update references in labels _, err = tx.ExecContext(ctx, `UPDATE labels SET issue_id = ? WHERE issue_id = ?`, newID, oldID) if err != nil { return fmt.Errorf("failed to update labels: %w", err) } // Update references in comments _, err = tx.ExecContext(ctx, `UPDATE comments SET issue_id = ? WHERE issue_id = ?`, newID, oldID) if err != nil { return fmt.Errorf("failed to update comments: %w", err) } // Update dirty_issues _, err = tx.ExecContext(ctx, ` INSERT INTO dirty_issues (issue_id, marked_at) VALUES (?, ?) ON DUPLICATE KEY UPDATE marked_at = VALUES(marked_at) `, newID, time.Now().UTC()) if err != nil { return fmt.Errorf("failed to mark issue dirty: %w", err) } // Delete old dirty entry _, err = tx.ExecContext(ctx, `DELETE FROM dirty_issues WHERE issue_id = ?`, oldID) if err != nil { return fmt.Errorf("failed to delete old dirty entry: %w", err) } // Record rename event _, err = tx.ExecContext(ctx, ` INSERT INTO events (issue_id, event_type, actor, old_value, new_value) VALUES (?, 'renamed', ?, ?, ?) `, newID, actor, oldID, newID) if err != nil { return fmt.Errorf("failed to record rename event: %w", err) } return tx.Commit() } // RenameDependencyPrefix updates the prefix in all dependency records func (s *DoltStore) RenameDependencyPrefix(ctx context.Context, oldPrefix, newPrefix string) error { tx, err := s.db.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } defer func() { _ = tx.Rollback() }() // Update issue_id column _, err = tx.ExecContext(ctx, ` UPDATE dependencies SET issue_id = CONCAT(?, SUBSTRING(issue_id, LENGTH(?) + 1)) WHERE issue_id LIKE CONCAT(?, '%') `, newPrefix, oldPrefix, oldPrefix) if err != nil { return fmt.Errorf("failed to update issue_id in dependencies: %w", err) } // Update depends_on_id column _, err = tx.ExecContext(ctx, ` UPDATE dependencies SET depends_on_id = CONCAT(?, SUBSTRING(depends_on_id, LENGTH(?) + 1)) WHERE depends_on_id LIKE CONCAT(?, '%') `, newPrefix, oldPrefix, oldPrefix) if err != nil { return fmt.Errorf("failed to update depends_on_id in dependencies: %w", err) } return tx.Commit() } // RenameCounterPrefix is a no-op with hash-based IDs func (s *DoltStore) RenameCounterPrefix(ctx context.Context, oldPrefix, newPrefix string) error { // Hash-based IDs don't use counters return nil }