From e08f1a9cbd582c73918e401eeba36261627f44a7 Mon Sep 17 00:00:00 2001 From: sebastian-sauer Date: Thu, 14 Dec 2023 10:26:59 +0100 Subject: [PATCH] Add combined index for issue_user.uid and issue_id (#28080) fixes #27877 --------- Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Lunny Xiao --- models/issues/issue_user.go | 4 +-- .../issue_user.yml | 20 +++++++++++ models/migrations/migrations.go | 2 ++ models/migrations/v1_22/main_test.go | 14 ++++++++ models/migrations/v1_22/v283.go | 34 +++++++++++++++++++ models/migrations/v1_22/v283_test.go | 28 +++++++++++++++ 6 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml create mode 100644 models/migrations/v1_22/main_test.go create mode 100644 models/migrations/v1_22/v283.go create mode 100644 models/migrations/v1_22/v283_test.go diff --git a/models/issues/issue_user.go b/models/issues/issue_user.go index 24bb74648d9c..6b59e0725ede 100644 --- a/models/issues/issue_user.go +++ b/models/issues/issue_user.go @@ -14,8 +14,8 @@ import ( // IssueUser represents an issue-user relation. type IssueUser struct { ID int64 `xorm:"pk autoincr"` - UID int64 `xorm:"INDEX"` // User ID. - IssueID int64 `xorm:"INDEX"` + UID int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID. + IssueID int64 `xorm:"INDEX unique(uid_to_issue)"` IsRead bool IsMentioned bool } diff --git a/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml b/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml new file mode 100644 index 000000000000..7bbb6f2f307f --- /dev/null +++ b/models/migrations/fixtures/Test_AddCombinedIndexToIssueUser/issue_user.yml @@ -0,0 +1,20 @@ +- + id: 1 + uid: 1 + issue_id: 1 + is_read: true + is_mentioned: false + +- + id: 2 + uid: 2 + issue_id: 1 + is_read: true + is_mentioned: false + +- + id: 3 + uid: 2 + issue_id: 1 # duplicated with id 2 + is_read: false + is_mentioned: true diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 28e3be503b29..578cbca035d8 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -550,6 +550,8 @@ var migrations = []Migration{ NewMigration("Add auth_token table", v1_22.CreateAuthTokenTable), // v282 -> v283 NewMigration("Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID), + // v283 -> v284 + NewMigration("Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_22/main_test.go b/models/migrations/v1_22/main_test.go new file mode 100644 index 000000000000..efd8dbaa8c6b --- /dev/null +++ b/models/migrations/v1_22/main_test.go @@ -0,0 +1,14 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func TestMain(m *testing.M) { + base.MainTest(m) +} diff --git a/models/migrations/v1_22/v283.go b/models/migrations/v1_22/v283.go new file mode 100644 index 000000000000..b2b94845d905 --- /dev/null +++ b/models/migrations/v1_22/v283.go @@ -0,0 +1,34 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import ( + "xorm.io/xorm" +) + +func AddCombinedIndexToIssueUser(x *xorm.Engine) error { + type OldIssueUser struct { + IssueID int64 + UID int64 + Cnt int64 + } + + var duplicatedIssueUsers []OldIssueUser + if err := x.SQL("select * from (select issue_id, uid, count(1) as cnt from issue_user group by issue_id, uid) a where a.cnt > 1"). + Find(&duplicatedIssueUsers); err != nil { + return err + } + for _, issueUser := range duplicatedIssueUsers { + if _, err := x.Exec("delete from issue_user where id in (SELECT id FROM issue_user WHERE issue_id = ? and uid = ? limit ?)", issueUser.IssueID, issueUser.UID, issueUser.Cnt-1); err != nil { + return err + } + } + + type IssueUser struct { + UID int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID. + IssueID int64 `xorm:"INDEX unique(uid_to_issue)"` + } + + return x.Sync(&IssueUser{}) +} diff --git a/models/migrations/v1_22/v283_test.go b/models/migrations/v1_22/v283_test.go new file mode 100644 index 000000000000..864f47f840c0 --- /dev/null +++ b/models/migrations/v1_22/v283_test.go @@ -0,0 +1,28 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import ( + "testing" + + "code.gitea.io/gitea/models/migrations/base" +) + +func Test_AddCombinedIndexToIssueUser(t *testing.T) { + type IssueUser struct { + UID int64 `xorm:"INDEX unique(uid_to_issue)"` // User ID. + IssueID int64 `xorm:"INDEX unique(uid_to_issue)"` + } + + // Prepare and load the testing database + x, deferable := base.PrepareTestEnv(t, 0, new(IssueUser)) + defer deferable() + if x == nil || t.Failed() { + return + } + + if err := AddCombinedIndexToIssueUser(x); err != nil { + t.Fatal(err) + } +}