]> source.dussan.org Git - gitea.git/commitdiff
Include OriginalAuthor in Reaction constraint (#13505)
authorzeripath <art27@cantab.net>
Tue, 10 Nov 2020 22:37:11 +0000 (22:37 +0000)
committerGitHub <noreply@github.com>
Tue, 10 Nov 2020 22:37:11 +0000 (22:37 +0000)
When migrating repositories with reactions with deleted users, the original
author id may be -1. This means that it is possible to end up attempting
to create multiple reactions with the same [ Type, IssueID, CommentID, UserID,
OriginalAuthorID ] thus breaking the constraints.

On SQLite this appears to cause a deadlock but on other dbs this will
cause the migration to fail.

This PR extends the constraint to include the original author username
in the constraint.

Fix #13271

Signed-off-by: Andrew Thornton <art27@cantab.net>
models/issue_reaction.go
models/migrations/migrations.go
models/migrations/v159.go [new file with mode: 0644]

index 50b9d6848a53338d42c0aad5d83ba8db730c9642..104afce5c192939bfca1871c640b097cdbc07fbd 100644 (file)
@@ -17,13 +17,13 @@ import (
 
 // Reaction represents a reactions on issues and comments.
 type Reaction struct {
-       ID               int64  `xorm:"pk autoincr"`
-       Type             string `xorm:"INDEX UNIQUE(s) NOT NULL"`
-       IssueID          int64  `xorm:"INDEX UNIQUE(s) NOT NULL"`
-       CommentID        int64  `xorm:"INDEX UNIQUE(s)"`
-       UserID           int64  `xorm:"INDEX UNIQUE(s) NOT NULL"`
-       OriginalAuthorID int64  `xorm:"INDEX UNIQUE(s) NOT NULL DEFAULT(0)"`
-       OriginalAuthor   string
+       ID               int64              `xorm:"pk autoincr"`
+       Type             string             `xorm:"INDEX UNIQUE(s) NOT NULL"`
+       IssueID          int64              `xorm:"INDEX UNIQUE(s) NOT NULL"`
+       CommentID        int64              `xorm:"INDEX UNIQUE(s)"`
+       UserID           int64              `xorm:"INDEX UNIQUE(s) NOT NULL"`
+       OriginalAuthorID int64              `xorm:"INDEX UNIQUE(s) NOT NULL DEFAULT(0)"`
+       OriginalAuthor   string             `xorm:"INDEX UNIQUE(s)"`
        User             *User              `xorm:"-"`
        CreatedUnix      timeutil.TimeStamp `xorm:"INDEX created"`
 }
index 4715f192c157eb868659f68d936e87363891dbc1..5a2646474c77fcb6bf3c19fcca3f4aabbbccb691 100644 (file)
@@ -252,6 +252,8 @@ var migrations = []Migration{
        NewMigration("ensure repo topics are up-to-date", fixRepoTopics),
        // v158 -> v159
        NewMigration("code comment replies should have the commitID of the review they are replying to", updateCodeCommentReplies),
+       // v159 -> v160
+       NewMigration("update reactions constraint", updateReactionConstraint),
 }
 
 // GetCurrentDBVersion returns the current db version
diff --git a/models/migrations/v159.go b/models/migrations/v159.go
new file mode 100644 (file)
index 0000000..68043b9
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+       "code.gitea.io/gitea/modules/timeutil"
+
+       "xorm.io/xorm"
+)
+
+func updateReactionConstraint(x *xorm.Engine) error {
+       // Reaction represents a reactions on issues and comments.
+       type Reaction struct {
+               ID               int64              `xorm:"pk autoincr"`
+               Type             string             `xorm:"INDEX UNIQUE(s) NOT NULL"`
+               IssueID          int64              `xorm:"INDEX UNIQUE(s) NOT NULL"`
+               CommentID        int64              `xorm:"INDEX UNIQUE(s)"`
+               UserID           int64              `xorm:"INDEX UNIQUE(s) NOT NULL"`
+               OriginalAuthorID int64              `xorm:"INDEX UNIQUE(s) NOT NULL DEFAULT(0)"`
+               OriginalAuthor   string             `xorm:"INDEX UNIQUE(s)"`
+               CreatedUnix      timeutil.TimeStamp `xorm:"INDEX created"`
+       }
+
+       sess := x.NewSession()
+       defer sess.Close()
+
+       if err := sess.Begin(); err != nil {
+               return err
+       }
+
+       if err := recreateTable(sess, &Reaction{}); err != nil {
+               return err
+       }
+
+       return sess.Commit()
+}