-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathhello.go
More file actions
105 lines (93 loc) · 2.83 KB
/
Copy pathhello.go
File metadata and controls
105 lines (93 loc) · 2.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Minimal walkthrough of the SQLRite Go driver.
//
// Prerequisite: build libsqlrite_c once from the repo root:
//
// cargo build --release -p sqlrite-ffi
//
// Then from inside examples/go/:
//
// go run hello.go
//
// Shape mirrors the standard library's `database/sql` API — if you've
// used any Go SQL driver (pq, mysql, sqlite3), you already know how
// to drive this.
package main
import (
"database/sql"
"fmt"
"log"
// Side-effect import registers "sqlrite" as a sql.Open driver name.
_ "github.com/joaoh82/rust_sqlite/sdk/go"
)
func main() {
// Pass `:memory:` for a transient in-memory DB (matching SQLite
// convention); pass a file path like "foo.sqlrite" for a file-
// backed DB that auto-saves on every write.
db, err := sql.Open("sqlrite", ":memory:")
if err != nil {
log.Fatalf("open: %v", err)
}
defer db.Close()
mustExec(db, "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
mustExec(db, "INSERT INTO users (name, age) VALUES ('alice', 30)")
mustExec(db, "INSERT INTO users (name, age) VALUES ('bob', 25)")
mustExec(db, "INSERT INTO users (name, age) VALUES ('carol', 40)")
// database/sql's Query + Scan — typed into Go primitives.
fmt.Println("All users:")
rows, err := db.Query("SELECT id, name, age FROM users")
if err != nil {
log.Fatalf("query: %v", err)
}
for rows.Next() {
var id, age int64
var name string
if err := rows.Scan(&id, &name, &age); err != nil {
log.Fatalf("scan: %v", err)
}
fmt.Printf(" %d: %s (%d)\n", id, name, age)
}
rows.Close()
// Transactions via database/sql: Begin, issue statements, commit
// or rollback. The engine treats this the same as `BEGIN` /
// `COMMIT` / `ROLLBACK` statements via Exec — auto-save is
// suppressed until the transaction commits, and Rollback
// restores the pre-BEGIN snapshot.
fmt.Println()
tx, err := db.Begin()
if err != nil {
log.Fatalf("begin: %v", err)
}
mustTxExec(tx, "INSERT INTO users (name, age) VALUES ('phantom', 99)")
fmt.Printf("Mid-transaction row count: %d\n", countRows(tx, "SELECT id FROM users"))
if err := tx.Rollback(); err != nil {
log.Fatalf("rollback: %v", err)
}
fmt.Printf("Post-rollback row count: %d\n", countRows(db, "SELECT id FROM users"))
}
// Small helpers — `database/sql`'s idiomatic error-handling gets
// noisy in example code, so we factor out two tiny wrappers.
type queryer interface {
Query(query string, args ...any) (*sql.Rows, error)
}
func mustExec(db *sql.DB, q string) {
if _, err := db.Exec(q); err != nil {
log.Fatalf("exec %q: %v", q, err)
}
}
func mustTxExec(tx *sql.Tx, q string) {
if _, err := tx.Exec(q); err != nil {
log.Fatalf("tx.Exec %q: %v", q, err)
}
}
func countRows(q queryer, sqlText string) int {
rows, err := q.Query(sqlText)
if err != nil {
log.Fatalf("query: %v", err)
}
defer rows.Close()
n := 0
for rows.Next() {
n++
}
return n
}