[performance] improved enum migrations (#3782)

* updates the enum migration to perform a singular update for all values, using an SQL case statement

* fix logging

* fix code comment

* well i guess we'll get rid of the useful but unused function then, linter. fine, i see how it is!

* append to byte buffer instead of WriteString() to shut the linter up (i know you're reading this, linter)
This commit is contained in:
kim 2025-02-11 15:58:44 +00:00 committed by GitHub
parent d0de3ad492
commit 37dbf319b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 18 deletions

View file

@ -71,7 +71,7 @@ func init() {
// we must drop all indices that rely on it. // we must drop all indices that rely on it.
log.Info(ctx, "dropping old visibility indexes...") log.Info(ctx, "dropping old visibility indexes...")
for _, index := range visIndices { for _, index := range visIndices {
log.Info(ctx, "dropping old index %s...", index.name) log.Infof(ctx, "dropping old index %s...", index.name)
if _, err := tx.NewDropIndex(). if _, err := tx.NewDropIndex().
Index(index.name). Index(index.name).
Exec(ctx); err != nil { Exec(ctx); err != nil {
@ -93,7 +93,7 @@ func init() {
// Recreate the visibility indices. // Recreate the visibility indices.
log.Info(ctx, "creating new visibility indexes...") log.Info(ctx, "creating new visibility indexes...")
for _, index := range visIndices { for _, index := range visIndices {
log.Info(ctx, "creating new index %s...", index.name) log.Infof(ctx, "creating new index %s...", index.name)
q := tx.NewCreateIndex(). q := tx.NewCreateIndex().
Table("statuses"). Table("statuses").
Index(index.name). Index(index.name).

View file

@ -82,26 +82,31 @@ func convertEnums[OldType ~string, NewType ~int16](
return gtserror.Newf("error selecting total count: %w", err) return gtserror.Newf("error selecting total count: %w", err)
} }
var updated int var args []any
for old, new := range mapping { var qbuf byteutil.Buffer
// Update old to new values. // Prepare a singular UPDATE statement using
res, err := tx.NewUpdate(). // SET $newColumn = (CASE $column WHEN $old THEN $new ... END)
Table(table). qbuf.B = append(qbuf.B, "UPDATE ? SET ? = (CASE ? "...)
Where("? = ?", bun.Ident(column), old). args = append(args, bun.Ident(table))
Set("? = ?", bun.Ident(newColumn), new). args = append(args, bun.Ident(newColumn))
Exec(ctx) args = append(args, bun.Ident(column))
for old, new := range mapping {
qbuf.B = append(qbuf.B, "WHEN ? THEN ? "...)
args = append(args, old, new)
}
qbuf.B = append(qbuf.B, "ELSE ? END)"...)
args = append(args, *defaultValue)
// Execute the prepared raw query with arguments.
res, err := tx.NewRaw(qbuf.String(), args...).Exec(ctx)
if err != nil { if err != nil {
return gtserror.Newf("error updating old column values: %w", err) return gtserror.Newf("error updating old column values: %w", err)
} }
// Count number items updated. // Count number items updated.
n, _ := res.RowsAffected() updated, _ := res.RowsAffected()
updated += int(n) if total != int(updated) {
}
// Check total updated.
if total != updated {
log.Warnf(ctx, "total=%d does not match updated=%d", total, updated) log.Warnf(ctx, "total=%d does not match updated=%d", total, updated)
} }