*sql.Tx and *sql.DB - should they share an interface?

1,831 views
Skip to first unread message

Eric Johnson

unread,
Jan 2, 2014, 8:39:20 PM1/2/14
to golan...@googlegroups.com
I'm noticing I'm writing SQL code where I wish to use the Exec(), Query(), or QueryRow() methods, but there's no interface shared by *sql.Tx and *sql.DB.

Which means my methods need to decide in advance whether or not a transaction is necessary for the operation. That seems unnecessary.

Am I missing something, or should I just file an issue that suggests the collection of the methods:

Exec
Prepare
Query
QueryRow

into a single interface (what to call said interface?). That way, the code that is manipulating data needn't be aware of whether it is using a transaction or the convenience functions on *sql.DB?

Eric.


Dave Cheney

unread,
Jan 2, 2014, 8:49:03 PM1/2/14
to Eric Johnson, golan...@googlegroups.com
You can define this interface in your code if you need it. 


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Frank Schröder

unread,
Jan 3, 2014, 3:37:32 AM1/3/14
to golan...@googlegroups.com
For one of my projects I've defined such an interface as a helper and was asking myself the same question. I've come to the conclusion that not having an interface is better since it makes it clear when a function requires transactions and when not. Also, this is helpful when you propagate an existing transaction to other (helper-)functions.

For testing I've used gocheck to start a TX for each test which gets rolled back at the end.

Frank

Toni Cárdenas

unread,
Jan 3, 2014, 6:16:18 AM1/3/14
to golan...@googlegroups.com
In a project I defined methods on a type SQLStore (CreateUser, DeleteThing, CheckWhatever, etc.). SQLStore is a struct with a SQLStoreIO member, SQLStoreIO being such common interface. So SQLStore can have inside either a transaction or a *sql.DB, and use all the custom methods with both.

For when, inside a method, I need to make sure I use a transaction, I defined a function:

func ensureTransaction(st *SQLStore) (store SQLStoreIO, commit, rollback func() error, err error)

If st is already a transaction (checked with a type assertion), `commit` and `rollback` are no-ops, as the transaction is supposed to be closed somewhere else, and the returned `store` is the same object than `st`. If not, it starts a new transaction in `store`, `commit` and `rollback` being its actual commit and rollback methods.
Reply all
Reply to author
Forward
0 new messages