Fix N+1 query pattern in export operations (bd-rcmg)
**Problem**: Export operations called GetLabels() and GetIssueComments() in a loop for each issue, creating N+1 query pattern. For 100 issues this created 201 queries instead of 3-5. **Solution**: - Added GetCommentsForIssues() batch method to storage interface - Implemented batch method in SQLite and memory storage backends - Updated handleExport() and triggerExport() to use batch queries - Added comprehensive tests for batch operations **Impact**: Query count reduced from ~201 to ~3-5 for 100 issues. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -81,3 +81,46 @@ func (s *SQLiteStorage) GetIssueComments(ctx context.Context, issueID string) ([
|
||||
|
||||
return comments, nil
|
||||
}
|
||||
|
||||
// GetCommentsForIssues fetches comments for multiple issues in a single query
|
||||
// Returns a map of issue_id -> []*Comment
|
||||
func (s *SQLiteStorage) GetCommentsForIssues(ctx context.Context, issueIDs []string) (map[string][]*types.Comment, error) {
|
||||
if len(issueIDs) == 0 {
|
||||
return make(map[string][]*types.Comment), nil
|
||||
}
|
||||
|
||||
// Build placeholders for IN clause
|
||||
placeholders := make([]interface{}, len(issueIDs))
|
||||
for i, id := range issueIDs {
|
||||
placeholders[i] = id
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(`
|
||||
SELECT id, issue_id, author, text, created_at
|
||||
FROM comments
|
||||
WHERE issue_id IN (%s)
|
||||
ORDER BY issue_id, created_at ASC
|
||||
`, buildPlaceholders(len(issueIDs))) // #nosec G201 -- placeholders are generated internally
|
||||
|
||||
rows, err := s.db.QueryContext(ctx, query, placeholders...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to batch get comments: %w", err)
|
||||
}
|
||||
defer func() { _ = rows.Close() }()
|
||||
|
||||
result := make(map[string][]*types.Comment)
|
||||
for rows.Next() {
|
||||
comment := &types.Comment{}
|
||||
err := rows.Scan(&comment.ID, &comment.IssueID, &comment.Author, &comment.Text, &comment.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to scan comment: %w", err)
|
||||
}
|
||||
result[comment.IssueID] = append(result[comment.IssueID], comment)
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error iterating comments: %w", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user