sql

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 15, 2024 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package sql is an implementation of trm.Transaction interface by Transaction for sql.Tx.

Example

Example demonstrates the implementation of the Repository pattern by trm.Manager.

package main

import (
	"context"
	"database/sql"
	"fmt"

	_ "github.com/mattn/go-sqlite3"

	trmsql "github.com/avito-tech/go-transaction-manager/sql"
	trmcontext "github.com/avito-tech/go-transaction-manager/trm/context"
	"github.com/avito-tech/go-transaction-manager/trm/manager"
)

// Example demonstrates the implementation of the Repository pattern by trm.Manager.
func main() {
	db, err := sql.Open("sqlite3", "file:test?mode=memory")
	checkErr(err)

	defer db.Close() //nolint:errcheck

	sqlStmt := `CREATE TABLE IF NOT EXISTS user (user_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, username TEXT);`
	_, err = db.Exec(sqlStmt)
	checkErr(err, sqlStmt)

	r := newRepo(db, trmsql.DefaultCtxGetter)

	u := &user{
		Username: "username",
	}

	ctx := context.Background()
	trManager := manager.Must(
		trmsql.NewDefaultFactory(db),
		manager.WithCtxManager(trmcontext.DefaultManager),
	)

	err = trManager.Do(ctx, func(ctx context.Context) error {
		if err := r.Save(ctx, u); err != nil {
			return err
		}

		return trManager.Do(ctx, func(ctx context.Context) error {
			u.Username = "new_username"

			return r.Save(ctx, u)
		})
	})
	checkErr(err)

	userFromDB, err := r.GetByID(ctx, u.ID)
	checkErr(err)

	fmt.Println(userFromDB)

}

type repo struct {
	db     *sql.DB
	getter *trmsql.CtxGetter
}

func newRepo(db *sql.DB, c *trmsql.CtxGetter) *repo {
	return &repo{
		db:     db,
		getter: c,
	}
}

type user struct {
	ID       int64
	Username string
}

func (r *repo) GetByID(ctx context.Context, id int64) (*user, error) {
	query := "SELECT * FROM user WHERE user_id = ?;"

	u := &user{}

	err := r.getter.DefaultTrOrDB(ctx, r.db).QueryRowContext(ctx, query, id).Scan(&u.ID, &u.Username)
	if err != nil {
		return nil, err
	}

	return u, nil
}

func (r *repo) Save(ctx context.Context, u *user) error {
	isNew := u.ID == 0

	args := []interface{}{
		sql.Named("username", u.Username),
	}
	query := `INSERT INTO user (username) VALUES (:username);`

	if !isNew {
		query = `UPDATE user SET username = :username WHERE user_id = :user_id;`

		args = append(args, sql.Named("user_id", u.ID))
	}

	res, err := r.getter.DefaultTrOrDB(ctx, r.db).ExecContext(ctx, query, args...)
	if err != nil {
		return err
	} else if !isNew {
		return nil
	} else if u.ID, err = res.LastInsertId(); err != nil {
		return err
	}

	// For PostgreSql need to use NamedQueryContext with RETURNING
	// DO UPDATE SET username = EXCLUDED.username RETURNING id;
	// defer res.Next()
	// if u.ID == 0 && res.Next() {
	//		if err = res.Scan(&u.ID); err != nil {
	//			return err
	//		}
	//	}

	return nil
}

func checkErr(err error, args ...interface{}) {
	if err != nil {
		panic(fmt.Sprint(append([]interface{}{err}, args...)...))
	}
}
Output:

&{1 new_username}

Index

Examples

Constants

This section is empty.

Variables

DefaultCtxGetter is the CtxGetter with settings.DefaultCtxKey.

Functions

func NewDefaultFactory

func NewDefaultFactory(db *sql.DB) trm.TrFactory

NewDefaultFactory creates default trm.Transaction(sql.Tx).

func NewFactory

func NewFactory(db *sql.DB, sp SavePoint) trm.TrFactory

NewFactory creates trm.Transaction(sql.Tx).

Types

type CtxGetter

type CtxGetter struct {
	// contains filtered or unexported fields
}

CtxGetter gets Tr from trm.СtxManager by casting trm.Transaction to Tr.

func NewCtxGetter

func NewCtxGetter(c trm.СtxManager) *CtxGetter

NewCtxGetter returns *CtxGetter to get Tr from context.Context.

func (*CtxGetter) DefaultTrOrDB

func (c *CtxGetter) DefaultTrOrDB(ctx context.Context, db Tr) Tr

DefaultTrOrDB returns Tr from context.Context or DB(Tr) otherwise.

func (*CtxGetter) TrOrDB

func (c *CtxGetter) TrOrDB(ctx context.Context, key trm.CtxKey, db Tr) Tr

TrOrDB returns Tr from context.Context by trm.CtxKey or DB(Tr) otherwise.

type DefaultSavePoint

type DefaultSavePoint struct{}

func NewSavePoint

func NewSavePoint() DefaultSavePoint

NewSavePoint is an implementation of trm.SavePoint.

func (DefaultSavePoint) Create

func (dsp DefaultSavePoint) Create(id string) string

func (DefaultSavePoint) Release

func (dsp DefaultSavePoint) Release(id string) string

func (DefaultSavePoint) Rollback

func (dsp DefaultSavePoint) Rollback(id string) string

type Opt

type Opt func(*Settings) error

Opt is a type to configure Settings.

func WithTxOptions

func WithTxOptions(opts *sql.TxOptions) Opt

WithTxOptions sets up sql.TxOptions for the Settings.

type SavePoint

type SavePoint interface {
	Create(id string) string
	Release(id string) string
	Rollback(id string) string
}

SavePoint defines the syntax to create savepoints within transaction.

type Settings

type Settings struct {
	trm.Settings
	// contains filtered or unexported fields
}

Settings contains settings for sql.Transaction.

func MustSettings

func MustSettings(trms trm.Settings, oo ...Opt) Settings

MustSettings returns Settings if err is nil and panics otherwise.

func NewSettings

func NewSettings(trms trm.Settings, oo ...Opt) (Settings, error)

NewSettings creates Settings.

func (Settings) EnrichBy

func (s Settings) EnrichBy(in trm.Settings) trm.Settings

EnrichBy fills nil properties from external Settings.

func (Settings) TxOpts

func (s Settings) TxOpts() *sql.TxOptions

TxOpts returns trm.CtxKey for the trm.Transaction.

type Tr

type Tr interface {
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
	Prepare(query string) (*sql.Stmt, error)

	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
	Exec(query string, args ...interface{}) (sql.Result, error)

	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
	Query(query string, args ...interface{}) (*sql.Rows, error)

	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
	QueryRow(query string, args ...interface{}) *sql.Row
}

Tr is an interface to work with sql.DB or sql.Tx. StmtContext and Stmt are not implemented!

type Transaction

type Transaction struct {
	// contains filtered or unexported fields
}

Transaction is trm.Transaction for sql.Tx. trm.NestedTrFactory returns IsActive as true while trm.Transaction is opened.

func NewTransaction

func NewTransaction(
	ctx context.Context,
	sp SavePoint,
	opts *sql.TxOptions,
	db *sql.DB,
) (context.Context, *Transaction, error)

NewTransaction creates trm.Transaction for sql.Tx.

func (*Transaction) Begin

Begin nested transaction by save point.

func (*Transaction) Closed added in v1.5.0

func (t *Transaction) Closed() <-chan struct{}

Closed returns a channel that's closed when transaction committed or rolled back.

func (*Transaction) Commit

func (t *Transaction) Commit(ctx context.Context) error

Commit the trm.Transaction.

func (*Transaction) IsActive

func (t *Transaction) IsActive() bool

IsActive returns true if the transaction started but not committed or rolled back.

func (*Transaction) Rollback

func (t *Transaction) Rollback(ctx context.Context) error

Rollback the trm.Transaction.

func (*Transaction) Transaction

func (t *Transaction) Transaction() interface{}

Transaction returns the real transaction sqlx.Tx.

Directories

Path Synopsis
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL