code.gitea.io/gitea@v1.22.3/models/db/sequence.go (about) 1 // Copyright 2018 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package db 5 6 import ( 7 "context" 8 "fmt" 9 "regexp" 10 11 "code.gitea.io/gitea/modules/setting" 12 ) 13 14 // CountBadSequences looks for broken sequences from recreate-table mistakes 15 func CountBadSequences(_ context.Context) (int64, error) { 16 if !setting.Database.Type.IsPostgreSQL() { 17 return 0, nil 18 } 19 20 sess := x.NewSession() 21 defer sess.Close() 22 23 var sequences []string 24 schema := x.Dialect().URI().Schema 25 26 sess.Engine().SetSchema("") 27 if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE 'tmp_recreate__%_id_seq%' AND sequence_catalog = ?", setting.Database.Name).Find(&sequences); err != nil { 28 return 0, err 29 } 30 sess.Engine().SetSchema(schema) 31 32 return int64(len(sequences)), nil 33 } 34 35 // FixBadSequences fixes for broken sequences from recreate-table mistakes 36 func FixBadSequences(_ context.Context) error { 37 if !setting.Database.Type.IsPostgreSQL() { 38 return nil 39 } 40 41 sess := x.NewSession() 42 defer sess.Close() 43 if err := sess.Begin(); err != nil { 44 return err 45 } 46 47 var sequences []string 48 schema := sess.Engine().Dialect().URI().Schema 49 50 sess.Engine().SetSchema("") 51 if err := sess.Table("information_schema.sequences").Cols("sequence_name").Where("sequence_name LIKE 'tmp_recreate__%_id_seq%' AND sequence_catalog = ?", setting.Database.Name).Find(&sequences); err != nil { 52 return err 53 } 54 sess.Engine().SetSchema(schema) 55 56 sequenceRegexp := regexp.MustCompile(`tmp_recreate__(\w+)_id_seq.*`) 57 58 for _, sequence := range sequences { 59 tableName := sequenceRegexp.FindStringSubmatch(sequence)[1] 60 newSequenceName := tableName + "_id_seq" 61 if _, err := sess.Exec(fmt.Sprintf("ALTER SEQUENCE `%s` RENAME TO `%s`", sequence, newSequenceName)); err != nil { 62 return err 63 } 64 if _, err := sess.Exec(fmt.Sprintf("SELECT setval('%s', COALESCE((SELECT MAX(id)+1 FROM `%s`), 1), false)", newSequenceName, tableName)); err != nil { 65 return err 66 } 67 } 68 69 return sess.Commit() 70 }