This commit is contained in:
tobi 2025-02-14 21:35:47 +01:00
commit eb537f49c0

View file

@ -112,10 +112,6 @@ func convertEnums[OldType ~string, NewType ~int16](
// in number of rows. // in number of rows.
const batchsz = 5000 const batchsz = 5000
// Prepare storage slice for each
// returned batch of column values.
vals := make([]string, 0, batchsz)
// Stores highest batch value // Stores highest batch value
// used in iterate queries, // used in iterate queries,
// starting at highest possible. // starting at highest possible.
@ -125,46 +121,58 @@ func convertEnums[OldType ~string, NewType ~int16](
var updated int var updated int
for { for {
// Reset values. // Limit to batchsz
vals = vals[:0] // items at once.
batchQ := tx.
NewSelect().
Table(table).
Column(batchByColumn).
Where("? < ?", bun.Ident(batchByColumn), highest).
OrderExpr("? DESC", bun.Ident(batchByColumn)).
Limit(batchsz)
// SELECT next batch of column values to iteratively update since embedding // Finalize UPDATE to operate on this batch only.
// it in the below UPDATE statement with RETURNING guarantees no return order.
if err := tx.NewRaw("SELECT ? FROM ? WHERE ? < ? ORDER BY ? DESC LIMIT ?",
bun.Ident(batchByColumn),
bun.Ident(table),
bun.Ident(batchByColumn),
highest,
bun.Ident(batchByColumn),
batchsz,
).Scan(ctx, &vals); err != nil {
return gtserror.Newf("error selecting batch: %w", err)
}
// Check if at end.
if len(vals) == 0 {
break
}
// Finalize UPDATE to operate on batch.
qStr := baseQStr + " WHERE ? IN (?)" qStr := baseQStr + " WHERE ? IN (?)"
args := append(slices.Clone(baseArgs), bun.Ident(batchByColumn)) args := append(
args = append(args, bun.In(vals)) slices.Clone(baseArgs),
bun.Ident(batchByColumn),
batchQ,
)
// Execute the prepared raw query with arguments. // Execute the prepared raw query with arguments.
_, err := tx.NewRaw(qStr, args...).Exec(ctx) res, err := tx.NewRaw(qStr, 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)
} }
// Update the count. // Check how many items we updated.
updated += len(vals) thisUpdated, err := res.RowsAffected()
if err != nil {
return gtserror.Newf("error counting affected rows: %w", err)
}
log.Infof(ctx, "updated %d of %d %s (up to %s)", if thisUpdated == 0 {
// Nothing updated
// means we're done.
break
}
// Update the overall count.
updated += int(thisUpdated)
// Log helpful message to admin.
log.Infof(ctx, "migrated %d of %d %s (up to %s)",
updated, total, table, highest) updated, total, table, highest)
// Get next highest. // Get next highest
highest = vals[0] // id for next batch.
if err := tx.
NewSelect().
With("batch_query", batchQ).
ColumnExpr("min(?) FROM ?", bun.Ident(batchByColumn), bun.Ident("batch_query")).
Scan(ctx, &highest); err != nil {
return gtserror.Newf("error selecting next highest: %w", err)
}
} }
if total != int(updated) { if total != int(updated) {