Skip to content

Commit 7884dc3

Browse files
authored
Merge pull request #4 from devlights/add-prepreadquery-in-tx
2 parents 75af27f + 10b8f65 commit 7884dc3

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

07.PreparedQueryInTx/Taskfile.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
vars:
6+
DBFILE: ./chinook.db
7+
8+
tasks:
9+
default:
10+
cmds:
11+
- cp -f ../chinook.db .
12+
- go run main.go
13+
- echo "SELECT * FROM artists ORDER BY ArtistId DESC LIMIT 10" | sqlite3 -header -table {{.DBFILE}}

07.PreparedQueryInTx/main.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package main
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"log"
7+
8+
_ "github.com/mattn/go-sqlite3"
9+
)
10+
11+
func init() {
12+
log.SetFlags(0)
13+
}
14+
15+
// 07.PreparedQueryInTx
16+
//
17+
// トランザクション (*sql.Tx) からも、Prepared Query を作成することが出来る。
18+
// この場合、その Prepared Query は、当該トランザクションに紐づいた状態となり
19+
// トランザクションの完了(Commit or Rollback)で、自動的にクローズされる。
20+
//
21+
// # REFERENCES
22+
// - https://go.dev/doc/database/execute-transactions
23+
// - https://go.dev/doc/database/prepared-statements
24+
// - https://pkg.go.dev/database/[email protected]#Tx
25+
// - https://pkg.go.dev/database/[email protected]#Tx.Prepare
26+
// - https://stackoverflow.com/a/25327191
27+
func main() {
28+
if err := run(); err != nil {
29+
log.Panic(err)
30+
}
31+
32+
/*
33+
$ task -d 07.PreparedQueryInTx/
34+
task: [default] cp -f ../chinook.db .
35+
task: [default] go run main.go
36+
id=990 affected=1
37+
id=991 affected=1
38+
id=992 affected=1
39+
id=993 affected=1
40+
id=994 affected=1
41+
id=995 affected=1
42+
id=996 affected=1
43+
id=997 affected=1
44+
id=998 affected=1
45+
id=999 affected=1
46+
task: [default] echo "SELECT * FROM artists ORDER BY ArtistId DESC LIMIT 10" | sqlite3 -header -table ./chinook.db
47+
+----------+---------+
48+
| ArtistId | Name |
49+
+----------+---------+
50+
| 999 | test999 |
51+
| 998 | test998 |
52+
| 997 | test997 |
53+
| 996 | test996 |
54+
| 995 | test995 |
55+
| 994 | test994 |
56+
| 993 | test993 |
57+
| 992 | test992 |
58+
| 991 | test991 |
59+
| 990 | test990 |
60+
+----------+---------+
61+
*/
62+
}
63+
64+
func run() error {
65+
var (
66+
db *sql.DB
67+
err error
68+
)
69+
70+
db, err = sql.Open("sqlite3", "chinook.db")
71+
if err != nil {
72+
return fmt.Errorf("sql.Open: %w", err)
73+
}
74+
defer db.Close()
75+
76+
var (
77+
tx *sql.Tx
78+
)
79+
80+
tx, err = db.Begin()
81+
if err != nil {
82+
return fmt.Errorf("db.Begin: %w", err)
83+
}
84+
defer tx.Rollback()
85+
86+
var (
87+
stmt *sql.Stmt
88+
)
89+
90+
stmt, err = tx.Prepare("INSERT INTO artists (ArtistId, Name) VALUES (?, ?)")
91+
if err != nil {
92+
return fmt.Errorf("db.Prepare: %w", err)
93+
}
94+
defer stmt.Close() // tx経由で *sql.Stmt を作成した場合、トランザクションと共にクローズされるので無くても良い
95+
96+
var (
97+
dropErr = func(v any, _ error) any { return v }
98+
)
99+
100+
for i := 990; i < 1000; i++ {
101+
var (
102+
rslt sql.Result
103+
)
104+
105+
rslt, err = stmt.Exec(i, fmt.Sprintf("test%d", i))
106+
if err != nil {
107+
return fmt.Errorf("*sql.Stmt.Exec (in tx): %w", err)
108+
}
109+
110+
log.Printf("id=%v\taffected=%v", dropErr(rslt.LastInsertId()), dropErr(rslt.RowsAffected()))
111+
}
112+
113+
err = tx.Commit()
114+
if err != nil {
115+
return fmt.Errorf("tx.Commit: %w", err)
116+
}
117+
118+
return nil
119+
}

0 commit comments

Comments
 (0)