[doctor] Add check/fix for bogus action rows (#19656)
Signed-off-by: Loïc Dachary <loic@dachary.org> Co-authored-by: Loïc Dachary <loic@dachary.org>
This commit is contained in:
parent
9fc194d2d9
commit
443675d180
3 changed files with 74 additions and 0 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
@ -246,3 +247,23 @@ func FixIssueLabelWithOutsideLabels() (int64, error) {
|
||||||
|
|
||||||
return res.RowsAffected()
|
return res.RowsAffected()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountActionCreatedUnixString count actions where created_unix is an empty string
|
||||||
|
func CountActionCreatedUnixString() (int64, error) {
|
||||||
|
if setting.Database.UseSQLite3 {
|
||||||
|
return db.GetEngine(db.DefaultContext).Where(`created_unix = ""`).Count(new(Action))
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FixActionCreatedUnixString set created_unix to zero if it is an empty string
|
||||||
|
func FixActionCreatedUnixString() (int64, error) {
|
||||||
|
if setting.Database.UseSQLite3 {
|
||||||
|
res, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return res.RowsAffected()
|
||||||
|
}
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -103,3 +104,46 @@ func TestUpdateMilestoneCounters(t *testing.T) {
|
||||||
assert.NoError(t, issues_model.UpdateMilestoneCounters(db.DefaultContext, issue.MilestoneID))
|
assert.NoError(t, issues_model.UpdateMilestoneCounters(db.DefaultContext, issue.MilestoneID))
|
||||||
unittest.CheckConsistencyFor(t, &issues_model.Milestone{})
|
unittest.CheckConsistencyFor(t, &issues_model.Milestone{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConsistencyUpdateAction(t *testing.T) {
|
||||||
|
if !setting.Database.UseSQLite3 {
|
||||||
|
t.Skip("Test is only for SQLite database.")
|
||||||
|
}
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
id := 8
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &Action{
|
||||||
|
ID: int64(id),
|
||||||
|
})
|
||||||
|
_, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = "" WHERE id = ?`, id)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
actions := make([]*Action, 0, 1)
|
||||||
|
//
|
||||||
|
// XORM returns an error when created_unix is a string
|
||||||
|
//
|
||||||
|
err = db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions)
|
||||||
|
if assert.Error(t, err) {
|
||||||
|
assert.Contains(t, err.Error(), "type string to a int64: invalid syntax")
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Get rid of incorrectly set created_unix
|
||||||
|
//
|
||||||
|
count, err := CountActionCreatedUnixString()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, count)
|
||||||
|
count, err = FixActionCreatedUnixString()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 1, count)
|
||||||
|
|
||||||
|
count, err = CountActionCreatedUnixString()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 0, count)
|
||||||
|
count, err = FixActionCreatedUnixString()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 0, count)
|
||||||
|
|
||||||
|
//
|
||||||
|
// XORM must be happy now
|
||||||
|
//
|
||||||
|
assert.NoError(t, db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions))
|
||||||
|
unittest.CheckConsistencyFor(t, &Action{})
|
||||||
|
}
|
||||||
|
|
|
@ -142,6 +142,12 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||||
Fixer: models.FixIssueLabelWithOutsideLabels,
|
Fixer: models.FixIssueLabelWithOutsideLabels,
|
||||||
FixedMessage: "Removed",
|
FixedMessage: "Removed",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "Action with created_unix set as an empty string",
|
||||||
|
Counter: models.CountActionCreatedUnixString,
|
||||||
|
Fixer: models.FixActionCreatedUnixString,
|
||||||
|
FixedMessage: "Set to zero",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: function to recalc all counters
|
// TODO: function to recalc all counters
|
||||||
|
@ -177,6 +183,9 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||||
// find access without repository
|
// find access without repository
|
||||||
genericOrphanCheck("Access entries without existing repository",
|
genericOrphanCheck("Access entries without existing repository",
|
||||||
"access", "repository", "access.repo_id=repository.id"),
|
"access", "repository", "access.repo_id=repository.id"),
|
||||||
|
// find action without repository
|
||||||
|
genericOrphanCheck("Action entries without existing repository",
|
||||||
|
"action", "repository", "action.repo_id=repository.id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, c := range consistencyChecks {
|
for _, c := range consistencyChecks {
|
||||||
|
|
Reference in a new issue