package pg_test import ( "bytes" "fmt" "strings" "sync" "time" "github.com/go-pg/pg" "github.com/go-pg/pg/orm" ) var pgdb *pg.DB func init() { pgdb = connect() err := pgdb.DropTable((*Flight)(nil), &orm.DropTableOptions{ IfExists: true, Cascade: true, }) panicIf(err) err = pgdb.CreateTable((*Flight)(nil), nil) panicIf(err) } func connect() *pg.DB { return pg.Connect(pgOptions()) } func panicIf(err error) { if err != nil { panic(err) } } func ExampleConnect() { db := pg.Connect(&pg.Options{ User: "postgres", Password: "", Database: "postgres", }) defer db.Close() var n int _, err := db.QueryOne(pg.Scan(&n), "SELECT 1") panicIf(err) fmt.Println(n) // Output: 1 } func ExampleDB_QueryOne() { var user struct { Name string } res, err := pgdb.QueryOne(&user, ` WITH users (name) AS (VALUES (?)) SELECT * FROM users `, "admin") panicIf(err) fmt.Println(res.RowsAffected()) fmt.Println(user) // Output: 1 // {admin} } func ExampleDB_QueryOne_returning_id() { _, err := pgdb.Exec(`CREATE TEMP TABLE users(id serial, name varchar(500))`) panicIf(err) var user struct { Id int32 Name string } user.Name = "admin" _, err = pgdb.QueryOne(&user, ` INSERT INTO users (name) VALUES (?name) RETURNING id `, &user) panicIf(err) fmt.Println(user) // Output: {1 admin} } func ExampleDB_Exec() { res, err := pgdb.Exec(`CREATE TEMP TABLE test()`) panicIf(err) fmt.Println(res.RowsAffected()) // Output: -1 } func ExampleListener() { ln := pgdb.Listen("mychan") defer ln.Close() ch := ln.Channel() go func() { time.Sleep(time.Millisecond) _, err := pgdb.Exec("NOTIFY mychan, ?", "hello world") panicIf(err) }() notif := <-ch fmt.Println(notif) // Output: &{mychan hello world} } func txExample() *pg.DB { db := pg.Connect(&pg.Options{ User: "postgres", }) queries := []string{ `DROP TABLE IF EXISTS tx_test`, `CREATE TABLE tx_test(counter int)`, `INSERT INTO tx_test (counter) VALUES (0)`, } for _, q := range queries { _, err := db.Exec(q) panicIf(err) } return db } func ExampleDB_Begin() { db := txExample() incrInTx := func(db *pg.DB) error { tx, err := db.Begin() if err != nil { return err } // Rollback tx on error. defer tx.Rollback() var counter int _, err = tx.QueryOne( pg.Scan(&counter), `SELECT counter FROM tx_test FOR UPDATE`) if err != nil { return err } counter++ _, err = tx.Exec(`UPDATE tx_test SET counter = ?`, counter) if err != nil { return err } return tx.Commit() } var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() err := incrInTx(db) panicIf(err) }() } wg.Wait() var counter int _, err := db.QueryOne(pg.Scan(&counter), `SELECT counter FROM tx_test`) panicIf(err) fmt.Println(counter) // Output: 10 } func ExampleDB_RunInTransaction() { db := txExample() incrInTx := func(db *pg.DB) error { // Transaction is automatically rollbacked on error. return db.RunInTransaction(func(tx *pg.Tx) error { var counter int _, err := tx.QueryOne( pg.Scan(&counter), `SELECT counter FROM tx_test FOR UPDATE`) if err != nil { return err } counter++ _, err = tx.Exec(`UPDATE tx_test SET counter = ?`, counter) return err }) } var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() err := incrInTx(db) panicIf(err) }() } wg.Wait() var counter int _, err := db.QueryOne(pg.Scan(&counter), `SELECT counter FROM tx_test`) panicIf(err) fmt.Println(counter) // Output: 10 } func ExampleDB_Prepare() { stmt, err := pgdb.Prepare(`SELECT $1::text, $2::text`) panicIf(err) var s1, s2 string _, err = stmt.QueryOne(pg.Scan(&s1, &s2), "foo", "bar") panicIf(err) fmt.Println(s1, s2) // Output: foo bar } func ExampleDB_CreateTable() { type Model1 struct { Id int } type Model2 struct { Id int Name string Model1Id int `sql:"on_delete:RESTRICT, on_update: CASCADE"` Model1 *Model1 } for _, model := range []interface{}{&Model1{}, &Model2{}} { err := pgdb.CreateTable(model, &orm.CreateTableOptions{ Temp: true, // create temp table FKConstraints: true, }) panicIf(err) } var info []struct { ColumnName string DataType string } _, err := pgdb.Query(&info, ` SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'model2' `) panicIf(err) fmt.Println(info) // Output: [{id bigint} {name text} {model1_id bigint}] } func ExampleInts() { var nums pg.Ints _, err := pgdb.Query(&nums, `SELECT generate_series(0, 10)`) panicIf(err) fmt.Println(nums) // Output: [0 1 2 3 4 5 6 7 8 9 10] } func ExampleStrings() { var strs pg.Strings _, err := pgdb.Query(&strs, ` WITH users AS (VALUES ('foo'), ('bar')) SELECT * FROM users `) panicIf(err) fmt.Println(strs) // Output: [foo bar] } func ExampleDB_CopyFrom() { _, err := pgdb.Exec(`CREATE TEMP TABLE words(word text, len int)`) panicIf(err) r := strings.NewReader("hello,5\nfoo,3\n") _, err = pgdb.CopyFrom(r, `COPY words FROM STDIN WITH CSV`) panicIf(err) var buf bytes.Buffer _, err = pgdb.CopyTo(&buf, `COPY words TO STDOUT WITH CSV`) panicIf(err) fmt.Println(buf.String()) // Output: hello,5 // foo,3 } func ExampleDB_WithTimeout() { var count int // Use bigger timeout since this query is known to be slow. _, err := pgdb.WithTimeout(time.Minute).QueryOne(pg.Scan(&count), ` SELECT count(*) FROM big_table `) panicIf(err) } func ExampleScan() { var s1, s2 string _, err := pgdb.QueryOne(pg.Scan(&s1, &s2), `SELECT ?, ?`, "foo", "bar") panicIf(err) fmt.Println(s1, s2) // Output: foo bar } func ExampleError() { flight := &Flight{ Id: 123, } err := pgdb.Insert(flight) panicIf(err) err = pgdb.Insert(flight) if err != nil { pgErr, ok := err.(pg.Error) if ok && pgErr.IntegrityViolation() { fmt.Println("flight already exists:", err) } else { panic(err) } } // Output: flight already exists: ERROR #23505 duplicate key value violates unique constraint "flights_pkey" }