code.gitea.io/gitea@v1.22.3/models/migrations/v1_22/v293.go (about) 1 // Copyright 2024 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package v1_22 //nolint 5 6 import ( 7 "code.gitea.io/gitea/modules/setting" 8 "code.gitea.io/gitea/modules/timeutil" 9 10 "xorm.io/xorm" 11 ) 12 13 // CheckProjectColumnsConsistency ensures there is exactly one default board per project present 14 func CheckProjectColumnsConsistency(x *xorm.Engine) error { 15 sess := x.NewSession() 16 defer sess.Close() 17 18 limit := setting.Database.IterateBufferSize 19 if limit <= 0 { 20 limit = 50 21 } 22 23 type Project struct { 24 ID int64 25 CreatorID int64 26 BoardID int64 27 } 28 29 type ProjectBoard struct { 30 ID int64 `xorm:"pk autoincr"` 31 Title string 32 Default bool `xorm:"NOT NULL DEFAULT false"` // issues not assigned to a specific board will be assigned to this board 33 Sorting int8 `xorm:"NOT NULL DEFAULT 0"` 34 Color string `xorm:"VARCHAR(7)"` 35 36 ProjectID int64 `xorm:"INDEX NOT NULL"` 37 CreatorID int64 `xorm:"NOT NULL"` 38 39 CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` 40 UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` 41 } 42 43 for { 44 if err := sess.Begin(); err != nil { 45 return err 46 } 47 48 // all these projects without defaults will be fixed in the same loop, so 49 // we just need to always get projects without defaults until no such project 50 var projects []*Project 51 if err := sess.Select("project.id as id, project.creator_id, project_board.id as board_id"). 52 Join("LEFT", "project_board", "project_board.project_id = project.id AND project_board.`default`=?", true). 53 Where("project_board.id is NULL OR project_board.id = 0"). 54 Limit(limit). 55 Find(&projects); err != nil { 56 return err 57 } 58 59 for _, p := range projects { 60 if _, err := sess.Insert(ProjectBoard{ 61 ProjectID: p.ID, 62 Default: true, 63 Title: "Uncategorized", 64 CreatorID: p.CreatorID, 65 }); err != nil { 66 return err 67 } 68 } 69 if err := sess.Commit(); err != nil { 70 return err 71 } 72 73 if len(projects) == 0 { 74 break 75 } 76 } 77 sess.Close() 78 79 return removeDuplicatedBoardDefault(x) 80 } 81 82 func removeDuplicatedBoardDefault(x *xorm.Engine) error { 83 type ProjectInfo struct { 84 ProjectID int64 85 DefaultNum int 86 } 87 var projects []ProjectInfo 88 if err := x.Select("project_id, count(*) AS default_num"). 89 Table("project_board"). 90 Where("`default` = ?", true). 91 GroupBy("project_id"). 92 Having("count(*) > 1"). 93 Find(&projects); err != nil { 94 return err 95 } 96 97 for _, project := range projects { 98 if _, err := x.Where("project_id=?", project.ProjectID). 99 Table("project_board"). 100 Limit(project.DefaultNum - 1). 101 Update(map[string]bool{ 102 "`default`": false, 103 }); err != nil { 104 return err 105 } 106 } 107 return nil 108 }