loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request '[PORT] gitea#30190: Add unique index for project_issue to prevent duplicate data' (#3096) from gusted/forgejo-gt-30190 into forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3096
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
Reviewed-by: Otto <otto@codeberg.org>

+124
+9
models/migrations/fixtures/Test_AddUniqueIndexForProjectIssue/project_issue.yml
··· 1 + - 2 + id: 1 3 + project_id: 1 4 + issue_id: 1 5 + 6 + - 7 + id: 2 8 + project_id: 1 9 + issue_id: 1
+5
models/migrations/migrations.go
··· 22 22 "code.gitea.io/gitea/models/migrations/v1_20" 23 23 "code.gitea.io/gitea/models/migrations/v1_21" 24 24 "code.gitea.io/gitea/models/migrations/v1_22" 25 + "code.gitea.io/gitea/models/migrations/v1_23" 25 26 "code.gitea.io/gitea/models/migrations/v1_6" 26 27 "code.gitea.io/gitea/models/migrations/v1_7" 27 28 "code.gitea.io/gitea/models/migrations/v1_8" ··· 574 575 NewMigration("Ensure every project has exactly one default column - No Op", noopMigration), 575 576 // v293 -> v294 576 577 NewMigration("Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency), 578 + 579 + // Gitea 1.22.0 ends at 294 580 + 581 + NewMigration("Add unique index for project issue table", v1_23.AddUniqueIndexForProjectIssue), 577 582 } 578 583 579 584 // GetCurrentDBVersion returns the current db version
+14
models/migrations/v1_23/main_test.go
··· 1 + // Copyright 2024 The Gitea Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package v1_23 //nolint 5 + 6 + import ( 7 + "testing" 8 + 9 + "code.gitea.io/gitea/models/migrations/base" 10 + ) 11 + 12 + func TestMain(m *testing.M) { 13 + base.MainTest(m) 14 + }
+44
models/migrations/v1_23/v294.go
··· 1 + // Copyright 2024 The Gitea Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package v1_23 //nolint 5 + 6 + import ( 7 + "xorm.io/xorm" 8 + ) 9 + 10 + // AddUniqueIndexForProjectIssue adds unique indexes for project issue table 11 + func AddUniqueIndexForProjectIssue(x *xorm.Engine) error { 12 + // remove possible duplicated records in table project_issue 13 + type result struct { 14 + IssueID int64 15 + ProjectID int64 16 + Cnt int 17 + } 18 + var results []result 19 + if err := x.Select("issue_id, project_id, count(*) as cnt"). 20 + Table("project_issue"). 21 + GroupBy("issue_id, project_id"). 22 + Having("count(*) > 1"). 23 + Find(&results); err != nil { 24 + return err 25 + } 26 + for _, r := range results { 27 + var ids []int64 28 + if err := x.SQL("SELECT id FROM project_issue WHERE issue_id = ? and project_id = ? limit ?", r.IssueID, r.ProjectID, r.Cnt-1).Find(&ids); err != nil { 29 + return err 30 + } 31 + if _, err := x.Table("project_issue").In("id", ids).Delete(); err != nil { 32 + return err 33 + } 34 + } 35 + 36 + // add unique index for project_issue table 37 + type ProjectIssue struct { //revive:disable-line:exported 38 + ID int64 `xorm:"pk autoincr"` 39 + IssueID int64 `xorm:"INDEX unique(s)"` 40 + ProjectID int64 `xorm:"INDEX unique(s)"` 41 + } 42 + 43 + return x.Sync(new(ProjectIssue)) 44 + }
+52
models/migrations/v1_23/v294_test.go
··· 1 + // Copyright 2024 The Gitea Authors. All rights reserved. 2 + // SPDX-License-Identifier: MIT 3 + 4 + package v1_23 //nolint 5 + 6 + import ( 7 + "slices" 8 + "testing" 9 + 10 + "code.gitea.io/gitea/models/migrations/base" 11 + 12 + "github.com/stretchr/testify/assert" 13 + "xorm.io/xorm/schemas" 14 + ) 15 + 16 + func Test_AddUniqueIndexForProjectIssue(t *testing.T) { 17 + type ProjectIssue struct { //revive:disable-line:exported 18 + ID int64 `xorm:"pk autoincr"` 19 + IssueID int64 `xorm:"INDEX"` 20 + ProjectID int64 `xorm:"INDEX"` 21 + } 22 + 23 + // Prepare and load the testing database 24 + x, deferable := base.PrepareTestEnv(t, 0, new(ProjectIssue)) 25 + defer deferable() 26 + if x == nil || t.Failed() { 27 + return 28 + } 29 + 30 + cnt, err := x.Table("project_issue").Where("project_id=1 AND issue_id=1").Count() 31 + assert.NoError(t, err) 32 + assert.EqualValues(t, 2, cnt) 33 + 34 + assert.NoError(t, AddUniqueIndexForProjectIssue(x)) 35 + 36 + cnt, err = x.Table("project_issue").Where("project_id=1 AND issue_id=1").Count() 37 + assert.NoError(t, err) 38 + assert.EqualValues(t, 1, cnt) 39 + 40 + tables, err := x.DBMetas() 41 + assert.NoError(t, err) 42 + assert.EqualValues(t, 1, len(tables)) 43 + found := false 44 + for _, index := range tables[0].Indexes { 45 + if index.Type == schemas.UniqueType { 46 + found = true 47 + slices.Equal(index.Cols, []string{"project_id", "issue_id"}) 48 + break 49 + } 50 + } 51 + assert.True(t, found) 52 + }