Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v7 api changed: how to new TxDatabase #95

Closed
chen56 opened this issue Jul 11, 2019 · 4 comments
Closed

v7 api changed: how to new TxDatabase #95

chen56 opened this issue Jul 11, 2019 · 4 comments

Comments

@chen56
Copy link
Contributor

chen56 commented Jul 11, 2019

in goqu.v5, i can use goqu.TxDatabase{...} create a goqu tx, but v7 how to do this :

func inTx_goqu_v5(sqlxTx *sqlx.Tx, txFunc func(tx *Tx) error) (err error) {
	tx := &Tx{sqlxTx, &goqu.TxDatabase{Dialect: sqlxTx.DriverName(), Tx: sqlxTx.Tx}}
	defer func() {
		if r := recover(); r != nil {
			//已在一个panic中,不理会Rollback的err
			err := tx.Rollback()
			logrus.Error(err)
			// re-throw panic after Rollback
			panic(r)
		}
		if err != nil {
			//err已非空,不理会Rollback的err
			err := tx.Rollback()
			logrus.Error(err)
			return
		}
		// err==nil, commit; 如果commit失败,则返回err
		err = tx.Commit()
	}()

	err = txFunc(tx)

	return err
}
@doug-martin
Copy link
Owner

The standard way of using this library for that would be to use db.Begin() however it looks like you're using sqlx, which is probably why you can't.

If I changed goqu to accept a interface ( since sqlx.DB and Tx both keep the same contract as sql.DB) when creating a goqu.Database would that suit your needs?

doug-martin added a commit that referenced this issue Jul 12, 2019
* Changed goqu.Database to accept a SQLDatabase interface to allow using goqu.Database with other libraries such as `sqlx`
@doug-martin doug-martin mentioned this issue Jul 12, 2019
@doug-martin
Copy link
Owner

I added the change I described in my previous comment. This should allow you to create a new goqu db instance with your sqlx instance. From there you can just do db.From to get a new transaction instance.

Let me know if this helps!

@chen56
Copy link
Contributor Author

chen56 commented Jul 12, 2019

thanks, You're so quick!

I have some Legacy Code (sqlx and goqu.v5) , mixture use sqlx and goqu.v5 in one tx

like this :

import (
	"context"
	"database/sql"
	"github.com/jmoiron/sqlx"
	"github.com/sirupsen/logrus"
	"gopkg.in/doug-martin/goqu.v5"
	_ "gopkg.in/doug-martin/goqu.v5/adapters/mysql"
)

func XXXXXXQuery(){
        mydatebase:=NewDb(sqlx.MustConnect("mysql", "localhost:3306................"))
	err = mydatebase.InTxContext(ctx, &sql.TxOptions{ReadOnly: true}, func(myTx *mysqlx.Tx) error {
               //use sqlx tx
               row := tx.Tx.QueryRowx("select * from abc")
               ...

               // use goqu Tx
	        found, err := tx.Goqu.From(goqu.I("abc").As("c")).Select("c.xxx").ScanStruct(&res)
               ...
		return err
	})

}        


// DB ext
type DB struct {
	DB   *sqlx.DB
	Goqu *goqu.Database
}

// Tx ext
type Tx struct {
	Tx   *sqlx.Tx
	Goqu *goqu.TxDatabase
}

// NewDb  
func NewDb(db *sqlx.DB) *DB {
	return &DB{
		DB:   db,
		Goqu: goqu.New("mysql", db.DB),
	}
}

// InTxContext  
func (db *DB) InTxContext(ctx context.Context, opts *sql.TxOptions, txFunc func(tx *Tx) error) (err error) {
	tx, err := db.DB.BeginTxx(ctx, opts)
	if err != nil {
		return
	}
	return inTx(tx, txFunc)
}

//InTx ref: https://stackoverflow.com/questions/16184238/database-sql-tx-detecting-commit-or-rollback
func (db *DB) InTx(txFunc func(tx *Tx) error) (err error) {
	tx, err := db.DB.Beginx()
	if err != nil {
		return
	}
	return inTx(tx, txFunc)
}

func inTx(sqlxTx *sqlx.Tx, txFunc func(tx *Tx) error) (err error) {
	tx := &Tx{sqlxTx, &goqu.TxDatabase{Dialect: sqlxTx.DriverName(), Tx: sqlxTx.Tx}}
	defer func() {
		if r := recover(); r != nil {
			//已在一个panic中,不理会Rollback的err
			err := tx.Tx.Rollback()
			logrus.Error(err)
			// re-throw panic after Rollback
			panic(r)
		}
		if err != nil {
			//err已非空,不理会Rollback的err
			err := tx.Tx.Rollback()
			logrus.Error(err)
			return
		}
		// err==nil, commit; 如果commit失败,则返回err
		err = tx.Tx.Commit()
	}()

	err = txFunc(tx)

	return err
}

in goqu.v7 , I saw your new code,Still unable to do this:

	goquTx, err := db.Goqu.Begin()
	if err != nil {
		return
	}
        myTx:=Tx{
             Tx:   ?????,  //  sqlx.Tx:    sqlx  also does not support NewTx(otherTx)
             goqu: goquTx,
        }

doug-martin added a commit that referenced this issue Jul 12, 2019
* [ADDED] Exposed `goqu.NewTx` to allow creating a goqu tx directly from a `sql.Tx` instead of using `goqu.Database#Begin` #95
@doug-martin doug-martin mentioned this issue Jul 12, 2019
@doug-martin
Copy link
Owner

Ok I added a goqu.NewTx function which you should be able to pass in the sqlx.Tx into to create a new goqu.TxDatabase

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants