Skip to content

Commit 32394f4

Browse files
committed
add sqlx
1 parent 19de79f commit 32394f4

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

awesome-go/sqlx/main.go

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package main
2+
3+
import (
4+
"database/sql"
5+
"fmt"
6+
"log"
7+
8+
"github.com/jmoiron/sqlx"
9+
_ "github.com/lib/pq"
10+
)
11+
12+
var schema = `
13+
CREATE TABLE person (
14+
first_name text,
15+
last_name text,
16+
email text
17+
);
18+
19+
CREATE TABLE place (
20+
country text,
21+
city text NULL,
22+
telcode INTEGER
23+
)`
24+
25+
type Person struct {
26+
FirstName string `db:"first_name"`
27+
LastName string `db:"last_name"`
28+
Email string
29+
}
30+
31+
type Place struct {
32+
Country string
33+
City sql.NullString
34+
TelCode int
35+
}
36+
37+
func main() {
38+
// this Pings the database trying to connect
39+
// use sqlx.Open() for sql.Open() semantics
40+
db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
41+
if err != nil {
42+
log.Fatalln(err)
43+
}
44+
45+
// exec the schema or fail; multi-statement Exec behavior varies between
46+
// database drivers; pq will exec them all, sqlite3 won't, ymmv
47+
db.MustExec(schema)
48+
49+
tx := db.MustBegin()
50+
tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "Jason", "Moiron", "[email protected]")
51+
tx.MustExec("INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "John", "Doe", "[email protected]")
52+
tx.MustExec("INSERT INTO place (country, city, telcode) VALUES ($1, $2, $3)", "United States", "New York", "1")
53+
tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Hong Kong", "852")
54+
tx.MustExec("INSERT INTO place (country, telcode) VALUES ($1, $2)", "Singapore", "65")
55+
// Named queries can use structs, so if you have an existing struct (i.e. person := &Person{}) that you have populated, you can pass it in as &person
56+
tx.NamedExec("INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)", &Person{"Jane", "Citizen", "[email protected]"})
57+
tx.Commit()
58+
59+
// Query the database, storing results in a []Person (wrapped in []interface{})
60+
people := []Person{}
61+
db.Select(&people, "SELECT * FROM person ORDER BY first_name ASC")
62+
jason, john := people[0], people[1]
63+
64+
fmt.Printf("%#v", jason)
65+
fmt.Printf("%#v", john)
66+
// Person{FirstName:"Jason", LastName:"Moiron", Email:"[email protected]"}
67+
// Person{FirstName:"John", LastName:"Doe", Email:"[email protected]"}
68+
69+
// You can also get a single result, a la QueryRow
70+
jason = Person{}
71+
err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason")
72+
fmt.Printf("%#v\n", jason)
73+
// Person{FirstName:"Jason", LastName:"Moiron", Email:"[email protected]"}
74+
75+
// if you have null fields and use SELECT *, you must use sql.Null* in your struct
76+
places := []Place{}
77+
err = db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
78+
if err != nil {
79+
fmt.Println(err)
80+
return
81+
}
82+
usa, singsing, honkers := places[0], places[1], places[2]
83+
84+
fmt.Printf("%#v\n%#v\n%#v\n", usa, singsing, honkers)
85+
// Place{Country:"United States", City:sql.NullString{String:"New York", Valid:true}, TelCode:1}
86+
// Place{Country:"Singapore", City:sql.NullString{String:"", Valid:false}, TelCode:65}
87+
// Place{Country:"Hong Kong", City:sql.NullString{String:"", Valid:false}, TelCode:852}
88+
89+
// Loop through rows using only one struct
90+
place := Place{}
91+
rows, err := db.Queryx("SELECT * FROM place")
92+
for rows.Next() {
93+
err := rows.StructScan(&place)
94+
if err != nil {
95+
log.Fatalln(err)
96+
}
97+
fmt.Printf("%#v\n", place)
98+
}
99+
// Place{Country:"United States", City:sql.NullString{String:"New York", Valid:true}, TelCode:1}
100+
// Place{Country:"Hong Kong", City:sql.NullString{String:"", Valid:false}, TelCode:852}
101+
// Place{Country:"Singapore", City:sql.NullString{String:"", Valid:false}, TelCode:65}
102+
103+
// Named queries, using `:name` as the bindvar. Automatic bindvar support
104+
// which takes into account the dbtype based on the driverName on sqlx.Open/Connect
105+
_, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`,
106+
map[string]interface{}{
107+
"first": "Bin",
108+
"last": "Smuth",
109+
"email": "[email protected]",
110+
})
111+
112+
// Selects Mr. Smith from the database
113+
rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:fn`, map[string]interface{}{"fn": "Bin"})
114+
115+
// Named queries can also use structs. Their bind names follow the same rules
116+
// as the name -> db mapping, so struct fields are lowercased and the `db` tag
117+
// is taken into consideration.
118+
rows, err = db.NamedQuery(`SELECT * FROM person WHERE first_name=:first_name`, jason)
119+
120+
// batch insert
121+
122+
// batch insert with structs
123+
personStructs := []Person{
124+
{FirstName: "Ardie", LastName: "Savea", Email: "[email protected]"},
125+
{FirstName: "Sonny Bill", LastName: "Williams", Email: "[email protected]"},
126+
{FirstName: "Ngani", LastName: "Laumape", Email: "[email protected]"},
127+
}
128+
129+
_, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
130+
VALUES (:first_name, :last_name, :email)`, personStructs)
131+
132+
// batch insert with maps
133+
personMaps := []map[string]interface{}{
134+
{"first_name": "Ardie", "last_name": "Savea", "email": "[email protected]"},
135+
{"first_name": "Sonny Bill", "last_name": "Williams", "email": "[email protected]"},
136+
{"first_name": "Ngani", "last_name": "Laumape", "email": "[email protected]"},
137+
}
138+
139+
_, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
140+
VALUES (:first_name, :last_name, :email)`, personMaps)
141+
}

0 commit comments

Comments
 (0)