Documentation ¶
Overview ¶
Example ¶
package main import ( "context" "database/sql" "errors" "fmt" "os" sqlmock "github.com/DATA-DOG/go-sqlmock" "github.com/jmoiron/sqlx" satomic "github.com/dhui/satomic/satomicx" "github.com/dhui/satomic/savepointers/mock" ) func main() { db, _sqlmock, err := sqlmock.New() if err != nil { fmt.Println("Error creating sqlmock:", err) return } defer db.Close() // nolint:errcheck type testSruct struct{ ID int } _sqlmock.ExpectBegin() _sqlmock.ExpectQuery("SELECT 1;").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1)) _sqlmock.ExpectExec("SAVEPOINT 1;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectQuery("SELECT 2;").WillReturnError(errors.New("select 2 error")) _sqlmock.ExpectExec("ROLLBACK TO 1;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectExec("SAVEPOINT 2;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectQuery("SELECT 3;").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(3)) _sqlmock.ExpectExec("RELEASE 2;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectExec("SAVEPOINT 3;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectQuery("SELECT 4;").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(4)) _sqlmock.ExpectExec("SAVEPOINT 4;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectQuery("SELECT 5;").WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(5)) _sqlmock.ExpectExec("SAVEPOINT 5;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectQuery("SELECT 6;").WillReturnError(errors.New("select 6 error")) _sqlmock.ExpectExec("ROLLBACK TO 5;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectExec("RELEASE 4;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectExec("RELEASE 3;").WillReturnResult(sqlmock.NewResult(0, 0)) _sqlmock.ExpectCommit() ctx := context.Background() // For actual code, use a real Savepointer instead of a mocked one q, err := satomic.NewQuerier(ctx, sqlx.NewDb(db, ""), mock.NewSavepointer(os.Stdout, true), sql.TxOptions{}) if err != nil { fmt.Println("Error creating Querier:", err) return } if err := q.Atomicx(func(ctx context.Context, q satomic.Querier) error { var dummy testSruct if err := q.GetContext(ctx, &dummy, "SELECT 1;"); err != nil { fmt.Println(err) } // SAVEPOINT 1 if err := q.Atomicx(func(ctx context.Context, q satomic.Querier) error { return q.GetContext(ctx, &dummy, "SELECT 2;") }); err != nil { fmt.Println(err) } // SAVEPOINT 2 if err := q.Atomicx(func(ctx context.Context, q satomic.Querier) error { return q.GetContext(ctx, &dummy, "SELECT 3;") }); err != nil { fmt.Println(err) } // SAVEPOINT 3 if err := q.Atomicx(func(ctx context.Context, q satomic.Querier) error { if err := q.GetContext(ctx, &dummy, "SELECT 4;"); err != nil { fmt.Println(err) } // SAVEPOINT 4 if err := q.Atomicx(func(ctx context.Context, q satomic.Querier) error { if err := q.GetContext(ctx, &dummy, "SELECT 5;"); err != nil { fmt.Println(err) } // SAVEPOINT 5 if err := q.Atomicx(func(ctx context.Context, q satomic.Querier) error { return q.GetContext(ctx, &dummy, "SELECT 6;") }); err != nil { fmt.Println(err) } return nil }); err != nil { fmt.Println(err) } return nil }); err != nil { fmt.Println(err) } return nil }); err != nil { fmt.Println(err) } if err := _sqlmock.ExpectationsWereMet(); err != nil { fmt.Println(err) } }
Output: SAVEPOINT 1; ROLLBACK TO 1; Err: "select 2 error" Atomic: <nil> SAVEPOINT 2; RELEASE 2; SAVEPOINT 3; SAVEPOINT 4; SAVEPOINT 5; ROLLBACK TO 5; Err: "select 6 error" Atomic: <nil> RELEASE 4; RELEASE 3;
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( // ErrDuplicateTransaction is the canonical error value when a Querier already has a transaction but // another transaction is being created ErrDuplicateTransaction = errors.New("Querier already has a transaction") // ErrDbMismatch is the canonical error value when a Querier's DB doesn't match the DB for creating a transaction ErrDbMismatch = errors.New("Querier DB doesn't match DB for transaction creation") )
Functions ¶
This section is empty.
Types ¶
type Querier ¶
type Querier interface { QuerierBase satomic.Querier Atomicx(f func(context.Context, Querier) error) *satomic.Error }
Querier provides an interface to interact with a SQL DB within an atomic transaction or savepoint
func NewQuerier ¶
func NewQuerier(ctx context.Context, db *sqlx.DB, savepointer savepointers.Savepointer, txOpts sql.TxOptions) (Querier, error)
NewQuerier creates a new Querier
type QuerierBase ¶
type QuerierBase interface { Get(interface{}, string, ...interface{}) error GetContext(context.Context, interface{}, string, ...interface{}) error Select(interface{}, string, ...interface{}) error SelectContext(context.Context, interface{}, string, ...interface{}) error Queryx(query string, args ...interface{}) (*sqlx.Rows, error) QueryxContext(ctx context.Context, query string, args ...interface{}) (*sqlx.Rows, error) QueryRowx(query string, args ...interface{}) *sqlx.Row QueryRowxContext(ctx context.Context, query string, args ...interface{}) *sqlx.Row }
QuerierBase provides an interface containing sqlx methods shared between sqlx.DB and sqlx.Tx
Doesn't embed the satomic.QuerierBase interface to avoid issues with duplicate methods
Click to show internal directories.
Click to hide internal directories.