go-transaction-manager

Форк
0
130 строк · 2.7 Кб
1
package sql_test
2

3
import (
4
	"context"
5
	"database/sql"
6
	"fmt"
7

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

10
	trmsql "github.com/avito-tech/go-transaction-manager/drivers/sql/v2"
11

12
	trmcontext "github.com/avito-tech/go-transaction-manager/trm/v2/context"
13

14
	"github.com/avito-tech/go-transaction-manager/trm/v2/manager"
15
)
16

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

22
	defer db.Close() //nolint:errcheck
23

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

28
	r := newRepo(db, trmsql.DefaultCtxGetter)
29

30
	u := &user{
31
		Username: "username",
32
	}
33

34
	ctx := context.Background()
35
	trManager := manager.Must(
36
		trmsql.NewDefaultFactory(db),
37
		manager.WithCtxManager(trmcontext.DefaultManager),
38
	)
39

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

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

48
			return r.Save(ctx, u)
49
		})
50
	})
51
	checkErr(err)
52

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

56
	fmt.Println(userFromDB)
57

58
	// Output: &{1 new_username}
59
}
60

61
type repo struct {
62
	db     *sql.DB
63
	getter *trmsql.CtxGetter
64
}
65

66
func newRepo(db *sql.DB, c *trmsql.CtxGetter) *repo {
67
	return &repo{
68
		db:     db,
69
		getter: c,
70
	}
71
}
72

73
type user struct {
74
	ID       int64
75
	Username string
76
}
77

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

81
	u := &user{}
82

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

88
	return u, nil
89
}
90

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

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

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

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

105
	res, err := r.getter.DefaultTrOrDB(ctx, r.db).ExecContext(ctx, query, args...)
106
	if err != nil {
107
		return err
108
	} else if !isNew {
109
		return nil
110
	} else if u.ID, err = res.LastInsertId(); err != nil {
111
		return err
112
	}
113

114
	// For PostgreSql need to use NamedQueryContext with RETURNING
115
	// DO UPDATE SET username = EXCLUDED.username RETURNING id;
116
	// defer res.Next()
117
	// if u.ID == 0 && res.Next() {
118
	//		if err = res.Scan(&u.ID); err != nil {
119
	//			return err
120
	//		}
121
	//	}
122

123
	return nil
124
}
125

126
func checkErr(err error, args ...interface{}) {
127
	if err != nil {
128
		panic(fmt.Sprint(append([]interface{}{err}, args...)...))
129
	}
130
}
131

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.