-
Notifications
You must be signed in to change notification settings - Fork 978
Description
I've been mocking up some changes to the generated interfaces to make using transactions easier, but I wanted to get opinions before I spend the time implementing it. The below snippets are using pgx, but it should translate similarly to database/sql as well.
// Shared interface between DB and Tx. This is unchanged from the current implementation.
interface DBTX {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
// DB is roughly equivalent to the pgx.Conn, but Begin is pgx.Conn's BeginEx, and
// I based BeginFunc on BoltDB's transactions because it provides a fairly ergonomic
// API once you get used to it.
// https://github.com/etcd-io/bbolt#transactions
interface DB {
DBTX
// Begin starts a transaction - be careful with this. You must either Commit or
// Rollback the transaction for the sake of your database.
Begin(ctx context.Context) (Tx, error)
// Begin starts a transaction and executes f. If f does not return an err, the transaction will be
// committed. If it does, then the transaction will be rolled back. BeginFunc returns the inner
// returned error.
BeginFunc(ctx context.Context, f (context.Context, Tx), error) error
}
interface Tx {
DBTX
CommitEx(ctx context.Context) error
RollbackEx(ctx context.Context) error
}Here is the main problem I've been running into - before I started switching to sqlc, I attached all the generated methods to the DBTX, but because of the possibility of using prepared queries with database/sql, this is not possible - in sqlc there is a concrete Queries type which all of them are attached to. There could be some unexported generated types, but that seems less than ideal. Do you have any ideas to solve that? Is this even worth pursuing? Are there better ways/APIs to make transactions easier to use?