@xiam xiam released this Feb 17, 2017 · 171 commits to v3 since this release

Assets 2


This release includes new features and overall design improvements.

  • db.v3 uses a new import path: upper.io/db.v3
go get -u upper.io/db.v3
// A regular query
res, err = sess.QueryContext(ctx, "SELECT * FROM authors")
// A transaction, all statements within this transaction run under the same context
sess.Tx(ctx, func() (tx sqlbuilder.Tx) error {
  res := tx.Find()
  // ...

With context.Context you'll be able to cancel queries or set a timeout. db.v3 provides you with different tools to make it easy to use context.Context:

sess := sess.WithContext(ctx) // A copy of `sess` on the given context.

res, err = sess.Query(...) // Will use the above `ctx` by default.

res, err = sess.QueryContext(anotherCtx, ...) // Uses a different context.

db.v3 can be compiled with go1.7 too (in this case, database/sql will ignore context features).

  • Provides per-database settings and logging (optional).
  • The query builder on db.v2 modified the internal query state everytime you used a method on it:
q := sess.SelectFrom("users")

q.Where(...) // This method modifies `q`'s internal state and returns the same `q`.

In v3, we decided to make the syntax more explicit to avoid potential side-effects.

q := sess.SelectFrom("users")
q = q.Where(...) // The `q` above does not get affected by Where(), unless we reassign `q`.

row, err := q.Query() // or q.QueryContext(ctx)

The new immutable behavior applies to all query builder methods:

q := sess.DeleteFrom("users").Where(...)
q = q.And(...)
q = q.Limit(5)

res, err := q.Exec() // Or q.ExecContext(ctx)
q := sess.Update("users").Set("foo", 3)
q = q.Where(...)

res, err := q.Exec() // Or q.ExecContext(ctx)
q := sess.InsertInto("users").Values(item1)
q = q.Values(item2)

res, err := q.Exec() // Or res.ExecContext(ctx)

And it also applies to db.And, db.Or and db.Result:

params := db.And(db.Cond{"foo" :1})
params = params.And(db.Cond{"bar": 1})

params := db.Or(db.Cond{"foo" :1})
params = params.Or(db.Cond{"bar": 1})
res := col.Find()
res = res.Limit(5).Offset(1)

err = res.One(&item)

This is an important difference from db.v2 that makes queries safer and more consistent.

Migration notes

For users who want to migrate from db.v2 to db.v3:

  • Remember to change all import paths to upper.io/db.v3
  • Use the dbcheck tool to find statements that you need to port to the new immutable syntax.
# Install dbcheck
go get -u github.com/upper/cmd/dbcheck

# Use "..." at the end to check all github.com/my/package's subpackages.
dbcheck github.com/my/package/...


Thanks to our awesome sponsor Pressly! we could not have done this without you.


Pressly makes it easy for enterprises to curate and share amazing content.