Skip to main content

Why not *sql.DB?

By default, *sql.DB does not implement the bob.Executor interface.

This is because the QueryContext() method of *sql.DB return an *sql.Rows object which is very difficult to mock or implement.

To be able to interoperate with other libraries and for ease of testing/mocking, Bob's Executor instead return a scan.Rows interface.

// Rows is an interface that is expected to be returned as the result of a query
type Rows interface {
Scan(...any) error
Columns() ([]string, error)
Next() bool
Close() error
Err() error
}

It is easy to convert an *sql.{DB,Tx,Conn} to a bob.Executor with bob.New()

db, err := sql.Open("postgres", "postgres://...")
bobExec := bob.New(db)

// For Transactions
tx, err := db.Begin()
bobExec = bob.New(tx) // using the transaction