MCPcopy Create free account
hub / github.com/bytebase/bytebase / BatchUpdateIssueStatuses

Method BatchUpdateIssueStatuses

backend/store/issue.go:447–511  ·  view source on GitHub ↗

BatchUpdateIssueStatuses updates the status of multiple issues. Returns a map of issueUID -> old status for the updated issues.

(ctx context.Context, projectID string, issueUIDs []int64, newStatus storepb.Issue_Status)

Source from the content-addressed store, hash-verified

445// BatchUpdateIssueStatuses updates the status of multiple issues.
446// Returns a map of issueUID -> old status for the updated issues.
447func (s *Store) BatchUpdateIssueStatuses(ctx context.Context, projectID string, issueUIDs []int64, newStatus storepb.Issue_Status) (map[int64]storepb.Issue_Status, error) {
448 tx, err := s.GetDB().BeginTx(ctx, nil)
449 if err != nil {
450 return nil, errors.Wrapf(err, "failed to begin transaction")
451 }
452 defer tx.Rollback()
453
454 // Fetch current issues to validate project membership and get old statuses.
455 fetchQuery := qb.Q().Space("SELECT id, status FROM issue WHERE id = ANY(?) AND project = ?", issueUIDs, projectID)
456 fetchSQL, fetchArgs, err := fetchQuery.ToSQL()
457 if err != nil {
458 return nil, errors.Wrapf(err, "failed to build fetch sql")
459 }
460
461 rows, err := tx.QueryContext(ctx, fetchSQL, fetchArgs...)
462 if err != nil {
463 return nil, errors.Wrapf(err, "failed to fetch issues")
464 }
465 defer rows.Close()
466
467 oldStatuses := make(map[int64]storepb.Issue_Status)
468 for rows.Next() {
469 var issueID int64
470 var statusString string
471 if err := rows.Scan(&issueID, &statusString); err != nil {
472 return nil, errors.Wrapf(err, "failed to scan issue")
473 }
474 statusValue, ok := storepb.Issue_Status_value[statusString]
475 if !ok {
476 return nil, errors.Errorf("invalid status string: %s", statusString)
477 }
478 issueStatus := storepb.Issue_Status(statusValue)
479
480 // Prevent changing status from DONE to other statuses.
481 if issueStatus == storepb.Issue_DONE && newStatus != storepb.Issue_DONE {
482 return nil, &common.Error{Code: common.Invalid, Err: errors.Errorf("cannot change status from DONE to %s for issue %d", newStatus.String(), issueID)}
483 }
484
485 oldStatuses[issueID] = issueStatus
486 }
487 if err := rows.Err(); err != nil {
488 return nil, errors.Wrapf(err, "failed to iterate rows")
489 }
490
491 // Validate that all requested issues were found in the project.
492 if len(oldStatuses) != len(issueUIDs) {
493 return nil, &common.Error{Code: common.Invalid, Err: errors.Errorf("expected %d issues in project %s, found %d", len(issueUIDs), projectID, len(oldStatuses))}
494 }
495
496 // Update the statuses.
497 updateQuery := qb.Q().Space("UPDATE issue SET status = ? WHERE id = ANY(?) AND project = ?", newStatus.String(), issueUIDs, projectID)
498 updateSQL, updateArgs, err := updateQuery.ToSQL()
499 if err != nil {
500 return nil, errors.Wrapf(err, "failed to build update sql")
501 }
502
503 if _, err := tx.ExecContext(ctx, updateSQL, updateArgs...); err != nil {
504 return nil, errors.Wrapf(err, "failed to update")

Callers 1

Calls 10

GetDBMethod · 0.95
QFunction · 0.92
SpaceMethod · 0.80
ToSQLMethod · 0.80
QueryContextMethod · 0.80
ScanMethod · 0.80
ErrorfMethod · 0.80
CloseMethod · 0.65
StringMethod · 0.65
NextMethod · 0.45

Tested by

no test coverage detected