[chore] Standardize database queries, use bun.Ident() properly (#886)

* use bun.Ident for user queries

* use bun.Ident for account queries

* use bun.Ident for media queries

* add DeleteAccount func

* remove CaseInsensitive in Where+use Ident ipv Safe

* update admin db

* update domain, use ident

* update emoji, use ident

* update instance queries, use bun.Ident

* fix media

* update mentions, use bun ident

* update relationship + tests

* use tableexpr

* add test follows to bun db test suite

* update notifications

* updatebyprimarykey => updatebyid

* fix session

* prefer explicit ID to pk

* fix little fucky wucky

* remove workaround

* use proper db func for attachment selection

* update status db

* add m2m entries in test rig

* fix up timeline

* go fmt

* fix status put issue

* update GetAccountStatuses
This commit is contained in:
tobi 2022-10-08 13:50:48 +02:00 committed by GitHub
commit aa07750bdb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 1074 additions and 570 deletions

View file

@ -34,38 +34,48 @@ type timelineDB struct {
}
func (t *timelineDB) GetHomeTimeline(ctx context.Context, accountID string, maxID string, sinceID string, minID string, limit int, local bool) ([]*gtsmodel.Status, db.Error) {
// Ensure reasonable
if limit < 0 {
limit = 0
}
// Make educated guess for slice size
statusIDs := make([]string, 0, limit)
q := t.conn.
NewSelect().
Table("statuses").
TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")).
// Select only IDs from table
Column("statuses.id").
Column("status.id").
// Find out who accountID follows.
Join("LEFT JOIN follows ON follows.target_account_id = statuses.account_id AND follows.account_id = ?", accountID).
Join("LEFT JOIN ? AS ? ON ? = ? AND ? = ?",
bun.Ident("follows"),
bun.Ident("follow"),
bun.Ident("follow.target_account_id"),
bun.Ident("status.account_id"),
bun.Ident("follow.account_id"),
accountID).
// Sort by highest ID (newest) to lowest ID (oldest)
Order("statuses.id DESC")
Order("status.id DESC")
if maxID != "" {
// return only statuses LOWER (ie., older) than maxID
q = q.Where("statuses.id < ?", maxID)
q = q.Where("? < ?", bun.Ident("status.id"), maxID)
}
if sinceID != "" {
// return only statuses HIGHER (ie., newer) than sinceID
q = q.Where("statuses.id > ?", sinceID)
q = q.Where("? > ?", bun.Ident("status.id"), sinceID)
}
if minID != "" {
// return only statuses HIGHER (ie., newer) than minID
q = q.Where("statuses.id > ?", minID)
q = q.Where("? > ?", bun.Ident("status.id"), minID)
}
if local {
// return only statuses posted by local account havers
q = q.Where("statuses.local = ?", local)
q = q.Where("? = ?", bun.Ident("status.local"), local)
}
if limit > 0 {
@ -78,13 +88,11 @@ func (t *timelineDB) GetHomeTimeline(ctx context.Context, accountID string, maxI
//
// This is equivalent to something like WHERE ... AND (... OR ...)
// See: https://bun.uptrace.dev/guide/queries.html#select
whereGroup := func(*bun.SelectQuery) *bun.SelectQuery {
q = q.WhereGroup(" AND ", func(*bun.SelectQuery) *bun.SelectQuery {
return q.
WhereOr("follows.account_id = ?", accountID).
WhereOr("statuses.account_id = ?", accountID)
}
q = q.WhereGroup(" AND ", whereGroup)
WhereOr("? = ?", bun.Ident("follow.account_id"), accountID).
WhereOr("? = ?", bun.Ident("status.account_id"), accountID)
})
if err := q.Scan(ctx, &statusIDs); err != nil {
return nil, t.conn.ProcessError(err)
@ -118,28 +126,28 @@ func (t *timelineDB) GetPublicTimeline(ctx context.Context, accountID string, ma
q := t.conn.
NewSelect().
Table("statuses").
Column("statuses.id").
Where("statuses.visibility = ?", gtsmodel.VisibilityPublic).
WhereGroup(" AND ", whereEmptyOrNull("statuses.in_reply_to_id")).
WhereGroup(" AND ", whereEmptyOrNull("statuses.in_reply_to_uri")).
WhereGroup(" AND ", whereEmptyOrNull("statuses.boost_of_id")).
Order("statuses.id DESC")
TableExpr("? AS ?", bun.Ident("statuses"), bun.Ident("status")).
Column("status.id").
Where("? = ?", bun.Ident("status.visibility"), gtsmodel.VisibilityPublic).
WhereGroup(" AND ", whereEmptyOrNull("status.in_reply_to_id")).
WhereGroup(" AND ", whereEmptyOrNull("status.in_reply_to_uri")).
WhereGroup(" AND ", whereEmptyOrNull("status.boost_of_id")).
Order("status.id DESC")
if maxID != "" {
q = q.Where("statuses.id < ?", maxID)
q = q.Where("? < ?", bun.Ident("status.id"), maxID)
}
if sinceID != "" {
q = q.Where("statuses.id > ?", sinceID)
q = q.Where("? > ?", bun.Ident("status.id"), sinceID)
}
if minID != "" {
q = q.Where("statuses.id > ?", minID)
q = q.Where("? > ?", bun.Ident("status.id"), minID)
}
if local {
q = q.Where("statuses.local = ?", local)
q = q.Where("? = ?", bun.Ident("status.local"), local)
}
if limit > 0 {
@ -181,15 +189,15 @@ func (t *timelineDB) GetFavedTimeline(ctx context.Context, accountID string, max
fq := t.conn.
NewSelect().
Model(&faves).
Where("account_id = ?", accountID).
Order("id DESC")
Where("? = ?", bun.Ident("status_fave.account_id"), accountID).
Order("status_fave.id DESC")
if maxID != "" {
fq = fq.Where("id < ?", maxID)
fq = fq.Where("? < ?", bun.Ident("status_fave.id"), maxID)
}
if minID != "" {
fq = fq.Where("id > ?", minID)
fq = fq.Where("? > ?", bun.Ident("status_fave.id"), minID)
}
if limit > 0 {