Sqlx: Generic *sqlx.DB or *sqlx.Tx?

Created on 27 Jul 2017  路  5Comments  路  Source: jmoiron/sqlx

Hi, is there a way I could accept a parameter which is either sqlx.DB or sqlx.Tx?

I have this function wherein I have to pass *sqlx.DB:

func GetUser(db *sqlx.DB, username string) ...

There's no problem with this, until I create a new Transaction and inside that transaction, I need to call GetUser. So I ended up implementing 2 functions to provide the same result...

func GetUser2(tx *sqlx.Tx, username string) ...

Is there a way I can make this into 1 function? I tried this:

func GetUser(db *sqlx.DB, tx *sqlx.Tx, username string) (*User, error) {
  if tx != nil {
    // use tx
  } else {
    // use db
  }
  ...
}

but is this okay? I wish there is something like this:

func GetUser(db *sqlx.DBorTxSomething, ...

:)

Most helpful comment

I'd still love to see this, bit of a pain to need yet-another layer. It'd be easy to argue it's not sqlx's concern, but sqlx exists to provide convenience so it seems fine to me.

All 5 comments

@mewben This is consistent with *sql.Tx and *sql.DB in the standard library.

Over in golang-nuts, @davecheney suggests defining your own interface.

See: https://groups.google.com/forum/#!topic/golang-nuts/yLg6IWbwPPw

@mewben I've achieved this by creating an interface that covers the sqlx methods I need and then creating two implementations that wrap sqlx.DB and sqlx.Tx respectively. Then your GetUser method can accept that interface instead of the concrete types.

Hey, you need to create a common interface that is used by both *sqlx.DB and *sqlx.Tx.
Example:

type DB interface {
    Querier
    Begin() (Tx, error)
    Close() error
}

type Tx interface {
    Querier
    Commit() error
    Rollback() error
}

type Querier interface {
    QueryRow(query string, args ...interface{}) Row
    Select(dest interface{}, query string, args ...interface{}) error
    NamedQuery(query string, arg interface{}) (Rows, error)
    NamedExec(query string, arg interface{}) (sql.Result, error)
}


func GetUser(q *Querier, username string) {}

But of course, it requires you to wrap sqlx :)

Ahhh.. I get it now.. Thank you all...

I'd still love to see this, bit of a pain to need yet-another layer. It'd be easy to argue it's not sqlx's concern, but sqlx exists to provide convenience so it seems fine to me.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ARolek picture ARolek  路  5Comments

MichaelHipp picture MichaelHipp  路  5Comments

webRat picture webRat  路  4Comments

wyattjoh picture wyattjoh  路  4Comments

railsmechanic picture railsmechanic  路  5Comments