mirror of
1
Fork 0

Don't use subselect in `DeleteIssuesByRepoID` (#27332) (#27408)

Backport #27332 by @JakobDev

Part of https://codeberg.org/forgejo/discussions/issues/61

This is workaround for a bug in MariaDB

Co-authored-by: JakobDev <jakobdev@gmx.de>
This commit is contained in:
Giteabot 2023-10-03 17:59:45 +08:00 committed by GitHub
parent 8c6464e39b
commit d5da0e622c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 79 additions and 64 deletions

View File

@ -696,85 +696,100 @@ func UpdateReactionsMigrationsByType(ctx context.Context, gitServiceType api.Git
// DeleteIssuesByRepoID deletes issues by repositories id // DeleteIssuesByRepoID deletes issues by repositories id
func DeleteIssuesByRepoID(ctx context.Context, repoID int64) (attachmentPaths []string, err error) { func DeleteIssuesByRepoID(ctx context.Context, repoID int64) (attachmentPaths []string, err error) {
deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"issue.repo_id": repoID}) // MariaDB has a performance bug: https://jira.mariadb.org/browse/MDEV-16289
// so here it uses "DELETE ... WHERE IN" with pre-queried IDs.
sess := db.GetEngine(ctx) sess := db.GetEngine(ctx)
// Delete content histories
if _, err = sess.In("issue_id", deleteCond).
Delete(&ContentHistory{}); err != nil {
return nil, err
}
// Delete comments and attachments for {
if _, err = sess.In("issue_id", deleteCond). issueIDs := make([]int64, 0, db.DefaultMaxInSize)
Delete(&Comment{}); err != nil {
return nil, err
}
// Dependencies for issues in this repository err := sess.Table(&Issue{}).Where("repo_id = ?", repoID).OrderBy("id").Limit(db.DefaultMaxInSize).Cols("id").Find(&issueIDs)
if _, err = sess.In("issue_id", deleteCond). if err != nil {
Delete(&IssueDependency{}); err != nil { return nil, err
return nil, err }
}
// Delete dependencies for issues in other repositories if len(issueIDs) == 0 {
if _, err = sess.In("dependency_id", deleteCond). break
Delete(&IssueDependency{}); err != nil { }
return nil, err
}
if _, err = sess.In("issue_id", deleteCond). // Delete content histories
Delete(&IssueUser{}); err != nil { _, err = sess.In("issue_id", issueIDs).Delete(&ContentHistory{})
return nil, err if err != nil {
} return nil, err
}
if _, err = sess.In("issue_id", deleteCond). // Delete comments and attachments
Delete(&Reaction{}); err != nil { _, err = sess.In("issue_id", issueIDs).Delete(&Comment{})
return nil, err if err != nil {
} return nil, err
}
if _, err = sess.In("issue_id", deleteCond). // Dependencies for issues in this repository
Delete(&IssueWatch{}); err != nil { _, err = sess.In("issue_id", issueIDs).Delete(&IssueDependency{})
return nil, err if err != nil {
} return nil, err
}
if _, err = sess.In("issue_id", deleteCond). // Delete dependencies for issues in other repositories
Delete(&Stopwatch{}); err != nil { _, err = sess.In("dependency_id", issueIDs).Delete(&IssueDependency{})
return nil, err if err != nil {
} return nil, err
}
if _, err = sess.In("issue_id", deleteCond). _, err = sess.In("issue_id", issueIDs).Delete(&IssueUser{})
Delete(&TrackedTime{}); err != nil { if err != nil {
return nil, err return nil, err
} }
if _, err = sess.In("issue_id", deleteCond). _, err = sess.In("issue_id", issueIDs).Delete(&Reaction{})
Delete(&project_model.ProjectIssue{}); err != nil { if err != nil {
return nil, err return nil, err
} }
if _, err = sess.In("dependent_issue_id", deleteCond). _, err = sess.In("issue_id", issueIDs).Delete(&IssueWatch{})
Delete(&Comment{}); err != nil { if err != nil {
return nil, err return nil, err
} }
var attachments []*repo_model.Attachment _, err = sess.In("issue_id", issueIDs).Delete(&Stopwatch{})
if err = sess.In("issue_id", deleteCond). if err != nil {
Find(&attachments); err != nil { return nil, err
return nil, err }
}
for j := range attachments { _, err = sess.In("issue_id", issueIDs).Delete(&TrackedTime{})
attachmentPaths = append(attachmentPaths, attachments[j].RelativePath()) if err != nil {
} return nil, err
}
if _, err = sess.In("issue_id", deleteCond). _, err = sess.In("issue_id", issueIDs).Delete(&project_model.ProjectIssue{})
Delete(&repo_model.Attachment{}); err != nil { if err != nil {
return nil, err return nil, err
} }
if _, err = db.DeleteByBean(ctx, &Issue{RepoID: repoID}); err != nil { _, err = sess.In("dependent_issue_id", issueIDs).Delete(&Comment{})
return nil, err if err != nil {
return nil, err
}
var attachments []*repo_model.Attachment
err = sess.In("issue_id", issueIDs).Find(&attachments)
if err != nil {
return nil, err
}
for j := range attachments {
attachmentPaths = append(attachmentPaths, attachments[j].RelativePath())
}
_, err = sess.In("issue_id", issueIDs).Delete(&repo_model.Attachment{})
if err != nil {
return nil, err
}
_, err = sess.In("id", issueIDs).Delete(&Issue{})
if err != nil {
return nil, err
}
} }
return attachmentPaths, err return attachmentPaths, err