README
¶
PostgreSQL client for Golang 
Supports:
- Basic types: integers, floats, string, bool, time.Time.
- sql.NullBool, sql.NullString, sql.NullInt64 and sql.NullFloat64.
sql:",null"
struct tag which marshalls zero struct fields as SQLNULL
and completely omits them fromINSERT
queries.- sql.Scanner and sql/driver.Valuer interfaces.
- Structs, maps and arrays are marshalled as JSON by default.
- PostgreSQL Arrays using array tag and Array wrapper.
- Transactions.
- Prepared statements.
- Notifications using
LISTEN
andNOTIFY
. - Copying data using
COPY FROM
andCOPY TO
. - Timeouts.
- Automatic connection pooling.
- Queries retries on network errors.
- Working with models using ORM and SQL.
- Scanning variables using ORM and SQL.
- SelectOrCreate using upserts.
- HasOne, HasMany and ManyToMany.
- Migrations.
- Sharding.
API docs: http://godoc.org/gopkg.in/pg.v4. Examples: http://godoc.org/gopkg.in/pg.v4#pkg-examples.
Table of contents
Installation
Install:
go get gopkg.in/pg.v4
Quickstart
package pg_test
import (
"fmt"
"gopkg.in/pg.v4"
)
type User struct {
Id int64
Name string
Emails []string
}
func (u User) String() string {
return fmt.Sprintf("User<%d %s %v>", u.Id, u.Name, u.Emails)
}
type Story struct {
Id int64
Title string
UserId int64
User *User
}
func (s Story) String() string {
return fmt.Sprintf("Story<%d %s %s>", s.Id, s.Title, s.User)
}
func createSchema(db *pg.DB) error {
queries := []string{
`CREATE TEMP TABLE users (id serial, name text, emails jsonb)`,
`CREATE TEMP TABLE stories (id serial, title text, user_id bigint)`,
}
for _, q := range queries {
_, err := db.Exec(q)
if err != nil {
return err
}
}
return nil
}
func ExampleDB_Query() {
db := pg.Connect(&pg.Options{
User: "postgres",
})
err := createSchema(db)
if err != nil {
panic(err)
}
user1 := &User{
Name: "admin",
Emails: []string{"admin1@admin", "admin2@admin"},
}
err = db.Create(user1)
if err != nil {
panic(err)
}
err = db.Create(&User{
Name: "root",
Emails: []string{"root1@root", "root2@root"},
})
if err != nil {
panic(err)
}
story1 := &Story{
Title: "Cool story",
UserId: user1.Id,
}
err = db.Create(story1)
if err != nil {
panic(err)
}
var user User
err = db.Model(&user).Where("id = ?", user1.Id).Select()
if err != nil {
panic(err)
}
var users []User
err = db.Model(&users).Select()
if err != nil {
panic(err)
}
var story Story
err = db.Model(&story).
Column("story.*", "User").
Where("story.id = ?", story1.Id).
Select()
if err != nil {
panic(err)
}
fmt.Println(user)
fmt.Println(users[0], users[1])
fmt.Println(story)
// Output: User<1 admin [admin1@admin admin2@admin]>
// User<1 admin [admin1@admin admin2@admin]> User<2 root [root1@root root2@root]>
// Story<1 Cool story User<1 admin [admin1@admin admin2@admin]>>
}
Howto
Please go through examples to get the idea how to use this package.
Writing queries
type Book struct {
Id int
Title string
Text string
}
// Insert new book returning primary keys.
err := db.Create(&book)
// INSERT INTO "books" (title, text) VALUES ('my title', 'my text') RETURNING "id"
// Insert new book returning all columns.
err := db.Model(&book).Returning("*").Create()
// INSERT INTO "books" (title, text) VALUES ('my title', 'my text') RETURNING *
// Select existing book by name or create new book.
err := db.Model(&book).
Where("title = ?title").
OnConflict("DO NOTHING"). // optional
SelectOrCreate()
// 1. SELECT * FROM "books" WHERE title = 'my title'
// 2. INSERT INTO "books" (title, text) VALUES ('my title', 'my text') RETURNING "id"
// 3. go to step 1 on error
// Update all columns except primary keys.
err := db.Update(&book)
// UPDATE "books" SET title = 'my title', text = 'my text' WHERE id = 1
// Update only column "title".
res, err := db.Model(&book).Set("title = ?title").Where("id = ?id").Update()
// UPDATE "books" SET title = 'my title' WHERE id = 1
// Update only column "title".
res, err := db.Model(&book).Column("title").Update()
// UPDATE "books" SET title = 'my title' WHERE id = 1
// Update only column "title".
res, err := db.Model(&book).UpdateValues(map[string]interface{}{
"title": book.Title,
})
// UPDATE "books" SET title = 'my title' WHERE id = 1
// Delete book by primary key.
err := db.Delete(&book)
// DELETE FROM "books" WHERE id = 1
// Delete book by title.
res, err := db.Model(&book).Where("title = ?title").Delete()
// Select book by primary key.
err := db.Select(&book)
// SELECT * FROM "books" WHERE id = 1
// Select book by title.
err := db.Model(&book).Where("title = ?title").Select()
// Select first 20 books.
err := db.Model(&books).Order("id ASC").Offset(0).Limit(20).Select()
// Count books.
count, err := db.Model(Book{}).Count()
Model definition
Models are defined using Go structs. Order of the struct fields usually does not matter with the only exception being primary key(s) that must defined before any other fields. Otherwise table relationshipts can be recognized incorrectly.
type Genre struct {
TableName struct{} `sql:"genres"` // specifies custom table name
Id int // Id is automatically detected as primary key
Name string
Rating int `sql:"-"` // - is used to ignore field
Books []Book `pg:",many2many:book_genres"` // many to many relation
ParentId int `sql:",null"`
Subgenres []Genre `pg:",fk:Parent"` // fk specifies prefix for foreign key (ParentId)
}
func (g Genre) String() string {
return fmt.Sprintf("Genre<Id=%d Name=%q>", g.Id, g.Name)
}
type Author struct {
ID int // both "Id" and "ID" are detected as primary key
Name string
Books []Book // has many relation
}
func (a Author) String() string {
return fmt.Sprintf("Author<ID=%d Name=%q>", a.ID, a.Name)
}
type BookGenre struct {
BookId int `sql:",pk"` // pk tag is used to mark field as primary key
GenreId int `sql:",pk"`
Genre_Rating int // belongs to and is copied to Genre model
}
type Book struct {
Id int
Title string
AuthorID int
Author *Author // has one relation
EditorID int
Editor *Author // has one relation
CreatedAt time.Time
Genres []Genre `pg:",many2many:book_genres" gorm:"many2many:book_genres;"` // many to many relation
Translations []Translation // has many relation
Comments []Comment `pg:",polymorphic:Trackable"` // has many polymorphic relation
}
func (b Book) String() string {
return fmt.Sprintf("Book<Id=%d Title=%q>", b.Id, b.Title)
}
type Translation struct {
Id int
BookId int
Book *Book // belongs to relation
Lang string
Comments []Comment `pg:",polymorphic:Trackable"` // has many polymorphic relation
}
type Comment struct {
TrackableId int `sql:",pk"` // Book.Id or Translation.Id
TrackableType string `sql:",pk"` // "book" or "translation"
Text string
}
FAQ
Why go-pg
-
No
rows.Close
to manually manage connections. -
go-pg automatically maps rows on Go structs and slice.
-
go-pg is 2x-10x faster than GORM on querying 100 rows from table.
BenchmarkQueryRowsGopgOptimized-4 10000 158443 ns/op 83432 B/op 625 allocs/op BenchmarkQueryRowsGopgReflect-4 10000 189014 ns/op 94759 B/op 826 allocs/op BenchmarkQueryRowsGopgORM-4 10000 199685 ns/op 95024 B/op 830 allocs/op BenchmarkQueryRowsStdlibPq-4 5000 242135 ns/op 161646 B/op 1324 allocs/op BenchmarkQueryRowsGORM-4 2000 704366 ns/op 396184 B/op 6767 allocs/op
-
go-pg generates much more effecient queries for joins.
Has one relationBenchmarkModelHasOneGopg-4 5000 313091 ns/op 78481 B/op 1290 allocs/op BenchmarkModelHasOneGORM-4 500 3849634 ns/op 1529982 B/op 71636 allocs/op
go-pg:
db.Model(&books).Column("book.*", "Author").Limit(100).Select()
SELECT "book".*, "author"."id" AS "author__id", "author"."name" AS "author__name" FROM "books" AS "book" LEFT JOIN "authors" AS "author" ON "author"."id" = "book"."author_id" LIMIT 100
GORM:
db.Preload("Author").Limit(100).Find(&books).Error
SELECT * FROM "books" LIMIT 100 SELECT * FROM "authors" WHERE ("id" IN ('1','2'...'100'))
Has many relationBenchmarkModelHasManyGopg-4 500 3034576 ns/op 409288 B/op 8700 allocs/op BenchmarkModelHasManyGORM-4 50 24677309 ns/op 10121839 B/op 519411 allocs/op
go-pg:
db.Model(&books).Column("book.*", "Translations").Limit(100).Select()
SELECT "book".* FROM "books" AS "book" LIMIT 100 SELECT "translation".* FROM "translations" AS "translation" WHERE ("translation"."book_id") IN ((100), (101), ... (199));
GORM:
db.Preload("Translations").Limit(100).Find(&books).Error
SELECT * FROM "books" LIMIT 100; SELECT * FROM "translations" WHERE ("book_id" IN (1, 2, ..., 100)); SELECT * FROM "authors" WHERE ("book_id" IN (1, 2, ..., 100));
Many to many relationBenchmarkModelHasMany2ManyGopg-4 500 3329123 ns/op 394738 B/op 9739 allocs/op BenchmarkModelHasMany2ManyGORM-4 200 7847630 ns/op 3350304 B/op 66239 allocs/op
go-pg:
db.Model(&books).Column("book.*", "Genres").Limit(100).Select()
SELECT "book"."id" FROM "books" AS "book" LIMIT 100; SELECT * FROM "genres" AS "genre" JOIN "book_genres" AS "book_genre" ON ("book_genre"."book_id") IN ((1), (2), ..., (100)) WHERE "genre"."id" = "book_genre"."genre_id";
GORM:
db.Preload("Genres").Limit(100).Find(&books).Error
SELECT * FROM "books" LIMIT 100; SELECT * FROM "genres" INNER JOIN "book_genres" ON "book_genres"."genre_id" = "genres"."id" WHERE ("book_genres"."book_id" IN ((1), (2), ..., (100)));
How can I view queries this library generates?
You can configure PostgreSQL to log every query by adding following lines to your postgresql.conf (usually /etc/postgresql/9.5/main/postgresql.conf):
log_statement = 'all'
log_min_duration_statement = 0
Then just tail the log file:
tail -f /var/log/postgresql/postgresql-9.5-main.log
Documentation
¶
Overview ¶
Package gopkg.in/pg.v4 implements a PostgreSQL client.
Index ¶
- Variables
- func Array(v interface{}) *types.Array
- func F(field string, params ...interface{}) types.F
- func Q(query string, params ...interface{}) types.Q
- func Scan(values ...interface{}) orm.ColumnScanner
- func SetLogger(logger *log.Logger)
- type DB
- func (db *DB) Begin() (*Tx, error)
- func (db *DB) Close() error
- func (db *DB) CopyFrom(r io.Reader, query interface{}, params ...interface{}) (*types.Result, error)
- func (db *DB) CopyTo(w io.Writer, query interface{}, params ...interface{}) (*types.Result, error)
- func (db *DB) Create(model interface{}) error
- func (db *DB) Delete(model interface{}) error
- func (db *DB) Exec(query interface{}, params ...interface{}) (res *types.Result, err error)
- func (db *DB) ExecOne(query interface{}, params ...interface{}) (*types.Result, error)
- func (db *DB) FormatQuery(dst []byte, query string, params ...interface{}) []byte
- func (db *DB) Listen(channels ...string) (*Listener, error)
- func (db *DB) Model(model interface{}) *orm.Query
- func (db *DB) Options() *Options
- func (db *DB) Prepare(q string) (*Stmt, error)
- func (db *DB) Query(model, query interface{}, params ...interface{}) (res *types.Result, err error)
- func (db *DB) QueryOne(model, query interface{}, params ...interface{}) (*types.Result, error)
- func (db *DB) RunInTransaction(fn func(*Tx) error) error
- func (db *DB) Select(model interface{}) error
- func (db *DB) Update(model interface{}) error
- func (db *DB) WithTimeout(d time.Duration) *DB
- type Error
- type IntSet
- type Ints
- type Listener
- type Options
- type Stmt
- func (stmt *Stmt) Close() error
- func (stmt *Stmt) Exec(params ...interface{}) (res *types.Result, err error)
- func (stmt *Stmt) ExecOne(params ...interface{}) (*types.Result, error)
- func (stmt *Stmt) Query(model interface{}, params ...interface{}) (res *types.Result, err error)
- func (stmt *Stmt) QueryOne(model interface{}, params ...interface{}) (*types.Result, error)
- type Strings
- type Tx
- func (tx *Tx) Commit() (err error)
- func (tx *Tx) CopyFrom(r io.Reader, query string, params ...interface{}) (*types.Result, error)
- func (tx *Tx) Create(model interface{}) error
- func (tx *Tx) Delete(model interface{}) error
- func (tx *Tx) Exec(query interface{}, params ...interface{}) (*types.Result, error)
- func (tx *Tx) ExecOne(query interface{}, params ...interface{}) (*types.Result, error)
- func (tx *Tx) FormatQuery(dst []byte, query string, params ...interface{}) []byte
- func (tx *Tx) Model(model interface{}) *orm.Query
- func (tx *Tx) Prepare(q string) (*Stmt, error)
- func (tx *Tx) Query(model interface{}, query interface{}, params ...interface{}) (*types.Result, error)
- func (tx *Tx) QueryOne(model interface{}, query interface{}, params ...interface{}) (*types.Result, error)
- func (tx *Tx) Rollback() (err error)
- func (tx *Tx) Select(model interface{}) error
- func (tx *Tx) Update(model interface{}) error
Examples ¶
- Array
- Connect
- DB.Begin
- DB.CopyFrom
- DB.Create
- DB.Create (OnConflict)
- DB.Create (SelectOrCreate)
- DB.Delete
- DB.Delete (MultipleRows)
- DB.Exec
- DB.Model
- DB.Model (CountRows)
- DB.Model (HasMany)
- DB.Model (HasOne)
- DB.Model (ManyToMany)
- DB.Model (NullEmptyValue)
- DB.Model (PostgresArrayStructTag)
- DB.Prepare
- DB.Query
- DB.QueryOne
- DB.QueryOne (Returning_id)
- DB.RunInTransaction
- DB.Select
- DB.Select (AllColumns)
- DB.Select (FirstRow)
- DB.Select (LastRow)
- DB.Select (SomeColumns)
- DB.Select (SomeColumnsIntoVars)
- DB.Update
- DB.Update (MultipleRows)
- DB.Update (SetValues)
- DB.Update (SomeColumns)
- DB.Update (SomeColumns2)
- DB.Update (UpdateValues)
- DB.WithTimeout
- F
- Ints
- Ints (In)
- Listener
- Q
- Scan
- Strings
Constants ¶
This section is empty.
Variables ¶
var ( ErrNoRows = internal.ErrNoRows ErrMultiRows = internal.ErrMultiRows )
var Discard orm.Discard
Discard is used with Query and QueryOne to discard rows.
Functions ¶
func Array ¶
Array returns an Array type that represents PostgreSQL array of any type.
Example ¶
Output: [one@example.com two@example.com]
func F ¶
F returns a ValueAppender that represents SQL identifier, e.g. table or column name.
Example ¶
Output: Book<Id=1 Title="book 1">
func Scan ¶
func Scan(values ...interface{}) orm.ColumnScanner
Scan returns ColumnScanner that copies the columns in the row into the values.
Example ¶
Output: foo bar <nil>
Types ¶
type DB ¶
type DB struct {
// contains filtered or unexported fields
}
DB is a database handle representing a pool of zero or more underlying connections. It's safe for concurrent use by multiple goroutines.
func Connect ¶
Connect connects to a database using provided options.
The returned DB is safe for concurrent use by multiple goroutines and maintains its own connection pool.
Example ¶
Output: <nil>
func (*DB) Begin ¶
Begin starts a transaction. Most callers should use RunInTransaction instead.
Example ¶
Output: 1
func (*DB) Close ¶
Close closes the database client, releasing any open resources.
It is rare to Close a DB, as the DB handle is meant to be long-lived and shared between many goroutines.
func (*DB) CopyFrom ¶
func (db *DB) CopyFrom(r io.Reader, query interface{}, params ...interface{}) (*types.Result, error)
CopyFrom copies data from reader to a table.
Example ¶
Output: hello,5 foo,3
func (*DB) Create ¶
Create inserts the model updating primary keys if they are empty.
Example ¶
Output: Book<Id=4 Title="new book">
Example (OnConflict) ¶
Output: created did nothing
Example (SelectOrCreate) ¶
Output: true Author<ID=2 Name="R. Scott Bakker">
func (*DB) Delete ¶
Delete deletes the model by primary key.
Example ¶
Output: pg: no rows in result set
Example (MultipleRows) ¶
Output: deleted 3 left 0
func (*DB) Exec ¶
Exec executes a query ignoring returned rows. The params are for any placeholder parameters in the query.
Example ¶
Output: -1 <nil>
func (*DB) ExecOne ¶
ExecOne acts like Exec, but query must affect only one row. It returns ErrNoRows error when query returns zero rows or ErrMultiRows when query returns multiple rows.
func (*DB) FormatQuery ¶
func (*DB) Model ¶
Model returns new query for the model.
Example ¶
Output: User<1 admin [admin1@admin admin2@admin]> User<1 admin [admin1@admin admin2@admin]> User<2 root [root1@root root2@root]> Story<1 Cool story User<1 admin [admin1@admin admin2@admin]>>
Example (CountRows) ¶
Output: 3
Example (HasMany) ¶
Output: Item 1 Subitems 2 3
Example (HasOne) ¶
Output: found 2 items item 2, subitem 1 item 4, subitem 2
Example (ManyToMany) ¶
Output: Item 1 Subitems 2 3
Example (NullEmptyValue) ¶
Output: false
Example (PostgresArrayStructTag) ¶
Output: {1 [one@example.com two@example.com] [123 321]}
func (*DB) Prepare ¶
Prepare creates a prepared statement for later queries or executions. Multiple queries or executions may be run concurrently from the returned statement.
Example ¶
Output: foo bar <nil>
func (*DB) Query ¶
Query executes a query that returns rows, typically a SELECT. The params are for any placeholder parameters in the query.
Example ¶
Output: User<1 admin [admin1@admin admin2@admin]> User<1 admin [admin1@admin admin2@admin]> User<2 root [root1@root root2@root]> Story<1 Cool story User<1 admin [admin1@admin admin2@admin]>>
func (*DB) QueryOne ¶
QueryOne acts like Query, but query must return only one row. It returns ErrNoRows error when query returns zero rows or ErrMultiRows when query returns multiple rows.
Example ¶
Output: 1 {admin}
Example (Returning_id) ¶
Output: {1 admin}
func (*DB) RunInTransaction ¶
RunInTransaction runs a function in a transaction. If function returns an error transaction is rollbacked, otherwise transaction is committed.
Example ¶
Output: 1
func (*DB) Select ¶
Select selects the model by primary key.
Example ¶
Output: Book<Id=1 Title="book 1">
Example (AllColumns) ¶
Output: Book<Id=1 Title="book 1"> 1
Example (FirstRow) ¶
Output: Book<Id=1 Title="book 1">
Example (LastRow) ¶
Output: Book<Id=3 Title="book 3">
Example (SomeColumns) ¶
Output: Book<Id=1 Title="">
Example (SomeColumnsIntoVars) ¶
Output: 1 book 1
func (*DB) Update ¶
Update updates the model by primary key.
Example ¶
Output: Book<Id=1 Title="updated book 1">
Example (MultipleRows) ¶
Output: Book<Id=1 Title="prefix book 1 suffix"> Book<Id=2 Title="prefix book 2 suffix">
Example (SetValues) ¶
Output: Book<Id=1 Title="prefix book 1 suffix">
Example (SomeColumns) ¶
Output: Book<Id=1 Title="updated book 1"> 1
Example (SomeColumns2) ¶
Output: Book<Id=1 Title="updated book 1"> 1
Example (UpdateValues) ¶
Output: Book<Id=1 Title="prefix book 1 suffix">
type IntSet ¶
type IntSet map[int64]struct{}
func (*IntSet) NewModel ¶
func (set *IntSet) NewModel() orm.ColumnScanner
type Ints ¶
type Ints []int64
Example ¶
Output: [0 1 2 3 4 5 6 7 8 9 10] <nil>
Example (In) ¶
Output: SELECT * FROM table WHERE id IN (1,2,3)
func (*Ints) NewModel ¶
func (ints *Ints) NewModel() orm.ColumnScanner
type Listener ¶
type Listener struct {
// contains filtered or unexported fields
}
Not thread-safe.
Example ¶
Output: mychan "hello world" <nil>
type Options ¶
type Options struct { // The network type, either tcp or unix. // Default is tcp. Network string // TCP host:port or Unix socket depending on Network. Addr string User string Password string Database string // Whether to use secure TCP/IP connections (TLS). SSL bool // PostgreSQL run-time configuration parameters to be set on connection. Params map[string]interface{} // The maximum number of retries before giving up. // Default is to not retry failed queries. MaxRetries int // The deadline for establishing new connections. If reached, // dial will fail with a timeout. // Default is 5 seconds. DialTimeout time.Duration // The timeout for socket reads. If reached, commands will fail // with a timeout error instead of blocking. // Default is no timeout. ReadTimeout time.Duration // The timeout for socket writes. If reached, commands will fail // with a timeout error instead of blocking. // Default is no timeout. WriteTimeout time.Duration // The maximum number of open socket connections. // Default is 10 connections. PoolSize int // The amount of time client waits for free connection if all // connections are busy before returning an error. // Default is 5 seconds. PoolTimeout time.Duration // The amount of time after which client closes idle connections. // Default is to not close idle connections. IdleTimeout time.Duration // The frequency of idle checks. // Default is 1 minute. IdleCheckFrequency time.Duration }
Database connection options.
type Stmt ¶
type Stmt struct {
// contains filtered or unexported fields
}
Stmt is a prepared statement. Stmt is safe for concurrent use by multiple goroutines.
func (*Stmt) ExecOne ¶
ExecOne acts like Exec, but query must affect only one row. It returns ErrNoRows error when query returns zero rows or ErrMultiRows when query returns multiple rows.
type Strings ¶
type Strings []string
Example ¶
Output: [foo bar] <nil>
func (Strings) AppendValue ¶
func (*Strings) NewModel ¶
func (strings *Strings) NewModel() orm.ColumnScanner
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Not thread-safe.
func (*Tx) ExecOne ¶
ExecOne acts like Exec, but query must affect only one row. It returns ErrNoRows error when query returns zero rows or ErrMultiRows when query returns multiple rows.
func (*Tx) FormatQuery ¶
func (*Tx) Query ¶
func (tx *Tx) Query(model interface{}, query interface{}, params ...interface{}) (*types.Result, error)
Query executes a query with the given parameters in a transaction.
func (*Tx) QueryOne ¶
func (tx *Tx) QueryOne(model interface{}, query interface{}, params ...interface{}) (*types.Result, error)
QueryOne acts like Query, but query must return only one row. It returns ErrNoRows error when query returns zero rows or ErrMultiRows when query returns multiple rows.