Fix FOREIGN KEY constraint failed when operating on non-existent issues
Fixes #325 - Fix CloseIssue to check rows affected before inserting event - Fix RemoveLabel to check rows affected before inserting event - Fix UpdateIssueID to check rows affected before inserting event - Prevent orphan events and confusing error messages Amp-Thread-ID: https://ampcode.com/threads/T-aa765a68-5cc4-465b-a2f6-aa008933c11e Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -20,11 +20,20 @@ func (s *SQLiteStorage) executeLabelOperation(
|
|||||||
operationError string,
|
operationError string,
|
||||||
) error {
|
) error {
|
||||||
return s.withTx(ctx, func(tx *sql.Tx) error {
|
return s.withTx(ctx, func(tx *sql.Tx) error {
|
||||||
_, err := tx.ExecContext(ctx, labelSQL, labelSQLArgs...)
|
result, err := tx.ExecContext(ctx, labelSQL, labelSQLArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s: %w", operationError, err)
|
return fmt.Errorf("%s: %w", operationError, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rows, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check rows affected: %w", err)
|
||||||
|
}
|
||||||
|
if rows == 0 {
|
||||||
|
// No change made (label already existed or didn't exist), so don't record event
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
_, err = tx.ExecContext(ctx, `
|
_, err = tx.ExecContext(ctx, `
|
||||||
INSERT INTO events (issue_id, event_type, actor, comment)
|
INSERT INTO events (issue_id, event_type, actor, comment)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
|
|||||||
@@ -711,7 +711,7 @@ func (s *SQLiteStorage) UpdateIssueID(ctx context.Context, oldID, newID string,
|
|||||||
}
|
}
|
||||||
defer func() { _ = tx.Rollback() }()
|
defer func() { _ = tx.Rollback() }()
|
||||||
|
|
||||||
_, err = tx.ExecContext(ctx, `
|
result, err := tx.ExecContext(ctx, `
|
||||||
UPDATE issues
|
UPDATE issues
|
||||||
SET id = ?, title = ?, description = ?, design = ?, acceptance_criteria = ?, notes = ?, updated_at = ?
|
SET id = ?, title = ?, description = ?, design = ?, acceptance_criteria = ?, notes = ?, updated_at = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
@@ -720,6 +720,14 @@ func (s *SQLiteStorage) UpdateIssueID(ctx context.Context, oldID, newID string,
|
|||||||
return fmt.Errorf("failed to update issue ID: %w", err)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
_, err = tx.ExecContext(ctx, `UPDATE dependencies SET issue_id = ? WHERE issue_id = ?`, newID, oldID)
|
_, err = tx.ExecContext(ctx, `UPDATE dependencies SET issue_id = ? WHERE issue_id = ?`, newID, oldID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to update issue_id in dependencies: %w", err)
|
return fmt.Errorf("failed to update issue_id in dependencies: %w", err)
|
||||||
@@ -812,7 +820,7 @@ func (s *SQLiteStorage) CloseIssue(ctx context.Context, id string, reason string
|
|||||||
}
|
}
|
||||||
defer func() { _ = tx.Rollback() }()
|
defer func() { _ = tx.Rollback() }()
|
||||||
|
|
||||||
_, err = tx.ExecContext(ctx, `
|
result, err := tx.ExecContext(ctx, `
|
||||||
UPDATE issues SET status = ?, closed_at = ?, updated_at = ?
|
UPDATE issues SET status = ?, closed_at = ?, updated_at = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
`, types.StatusClosed, now, now, id)
|
`, types.StatusClosed, now, now, id)
|
||||||
@@ -820,6 +828,14 @@ func (s *SQLiteStorage) CloseIssue(ctx context.Context, id string, reason string
|
|||||||
return fmt.Errorf("failed to close issue: %w", err)
|
return fmt.Errorf("failed to close issue: %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", id)
|
||||||
|
}
|
||||||
|
|
||||||
_, err = tx.ExecContext(ctx, `
|
_, err = tx.ExecContext(ctx, `
|
||||||
INSERT INTO events (issue_id, event_type, actor, comment)
|
INSERT INTO events (issue_id, event_type, actor, comment)
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
|
|||||||
Reference in New Issue
Block a user