uptrace / bun

SQL-first Golang ORM
https://bun.uptrace.dev
BSD 2-Clause "Simplified" License
3.83k stars 230 forks source link

feat: Enhance Apply method to accept multiple functions #1049

Closed Tiscs closed 2 weeks ago

Tiscs commented 2 weeks ago

This pull request includes updates to the Apply method across multiple query types to support variadic function arguments, allowing multiple functions to be applied in sequence, these changes will not break existing calls.

type UsersRepo interface {
    // Implemention:
    //
    // var users []*models.User
    // query := r.bdb.NewSelect().Model(&users).Apply(fns...)
    // return query.ScanAndCount(ctx)
    //
    // Example 1:
    //
    //   // find users 
    //   users, _, err := usersRepo.FindUsers(ctx,
    //       func(sq *bun.SelectQuery) *bun.SelectQuery {
    //           return sq.Where("age > ?", 59).Order("age DESC")
    //       },
    //       func(sq *bun.SelectQuery) *bun.SelectQuery {
    //           return sq.Offset(0).Limit(100)
    //       },
    //   )
    FindUsers(ctx context.Context, fns ...func(*bun.SelectQuery) *bun.SelectQuery) ([]*models.User, int, error)
}

BTW, some comments were fixed.

j2gg0s commented 2 weeks ago

Thanks for your contribution!

However, I think Query is chainable, so could we achieve the same effect with the following approach?

db.NewSelect().Model(new(User)).Apply(fn1).Apply(fn2)
Tiscs commented 2 weeks ago

Thanks for your contribution!

However, I think Query is chainable, so could we achieve the same effect with the following approach?

db.NewSelect().Model(new(User)).Apply(fn1).Apply(fn2)

Thanks for your response.

That's right, the query can be implemented in your way.

But in my case, I build the query by passing in variadic parameters, so I need to do it like this:

q := db.NewSelect().Model(new(User))
for _, fn := range fns {
    fn(q) // or `q = fn(q)`, queries are modified in-place
}
q.Scan(ctx)

So, I think chainable queries are great, and applying multiple at once is also useful.