[bugfix] fix issues with postgres array serialization (#4295)

thank you to @kipvandenbos -erino for figuring this out!

Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4295
Co-authored-by: kim <grufwub@gmail.com>
Co-committed-by: kim <grufwub@gmail.com>
This commit is contained in:
kim 2025-06-26 14:17:47 +02:00 committed by kim
commit 39b11dbfb6
4 changed files with 38 additions and 2 deletions

View file

@ -196,13 +196,17 @@ func (m *mediaDB) DeleteAttachment(ctx context.Context, id string) error {
})
if len(updatedIDs) != len(status.AttachmentIDs) {
// Convert to bun array for serialization.
arrIDs := bunArrayType(tx, updatedIDs)
// Note: this handles not found.
//
// Attachments changed, update the status.
if _, err := tx.NewUpdate().
Table("statuses").
Where("? = ?", bun.Ident("id"), status.ID).
Set("? = ?", bun.Ident("attachment_ids"), updatedIDs).
Set("? = ?", bun.Ident("attachment_ids"), arrIDs).
Exec(ctx); err != nil {
return gtserror.Newf("error updating status: %w", err)
}

View file

@ -110,12 +110,16 @@ func init() {
return gtserror.Newf("error selecting %T ids: %w", data.Model, err)
}
// Convert related IDs to bun array
// type for serialization in query.
arrIDs := bunArrayType(tx, relatedIDs)
// Now update the relevant filter
// row to contain these related IDs.
if _, err := tx.NewUpdate().
Model((*newmodel.Filter)(nil)).
Where("? = ?", bun.Ident("id"), filterID).
Set("? = ?", bun.Ident(col), relatedIDs).
Set("? = ?", bun.Ident(col), arrIDs).
Exec(ctx); err != nil {
return gtserror.Newf("error updating filters.%s ids: %w", col, err)
}

View file

@ -34,10 +34,24 @@ import (
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/feature"
"github.com/uptrace/bun/dialect/pgdialect"
"github.com/uptrace/bun/dialect/sqltype"
"github.com/uptrace/bun/schema"
)
// bunArrayType wraps the given type in a pgdialect.Array
// if needed, which postgres wants for serializing arrays.
func bunArrayType(db bun.IDB, arr any) any {
switch db.Dialect().Name() {
case dialect.SQLite:
return arr // return as-is
case dialect.PG:
return pgdialect.Array(arr)
default:
panic("unreachable")
}
}
// doWALCheckpoint attempt to force a WAL file merge on SQLite3,
// which can be useful given how much can build-up in the WAL.
//

View file

@ -29,6 +29,7 @@ import (
"code.superseriousbusiness.org/gotosocial/internal/paging"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect"
"github.com/uptrace/bun/dialect/pgdialect"
)
// likeEscaper is a thread-safe string replacer which escapes
@ -60,6 +61,19 @@ func likeOperator(query *bun.SelectQuery) string {
return ""
}
// bunArrayType wraps the given type in a pgdialect.Array
// if needed, which postgres wants for serializing arrays.
func bunArrayType(db bun.IDB, arr any) any {
switch db.Dialect().Name() {
case dialect.SQLite:
return arr // return as-is
case dialect.PG:
return pgdialect.Array(arr)
default:
panic("unreachable")
}
}
// whereLike appends a WHERE clause to the
// given SelectQuery, which searches for
// matches of `search` in the given subQuery